// static HPOINTER QPixmap::toPmHPOINTER(const QIcon &icon, bool isPointer, int hotX, int hotY, bool embedRealAlpha, bool isMini) { if (icon.isNull()) return NULLHANDLE; // get the system icon size int w = WinQuerySysValue(HWND_DESKTOP, isPointer ? SV_CXPOINTER : SV_CXICON); int h = WinQuerySysValue(HWND_DESKTOP, isPointer ? SV_CYPOINTER : SV_CYICON); if (!isPointer && isMini) { w = w / 2; h = h / 2; } // obtain the closest (but never larger) icon size we have QSize size = icon.actualSize(QSize(w, h)); QPixmap pm = icon.pixmap(size); if (pm.isNull()) return NULLHANDLE; // if we got a smaller pixmap then center it inside the box matching the // system size instead of letting WinCreatePointerIndirect() scale (this // covers a usual case when we get 32/16 px pixmaps on a 120 DPI system // where the icon size is 40/20 px respectively): scaling such small images // looks really ugly. if (!pm.isNull() && (pm.width() < w || pm.height() < h)) { Q_ASSERT(pm.width() <= w && pm.height() <= h); QPixmap pmNew(w, h); pmNew.fill(Qt::transparent); QPainter painter(&pmNew); int dx = (w - pm.width()) / 2; int dy = (h - pm.height()) / 2; painter.drawPixmap(dx, dy, pm); pm = pmNew; hotX += dx; hotY += dy; } POINTERINFO info; info.fPointer = isPointer; info.xHotspot = hotX; info.yHotspot = pm.height() - hotY - 1; info.hbmColor = pm.toPmHBITMAP(&info.hbmPointer, embedRealAlpha); info.hbmMiniPointer = NULLHANDLE; info.hbmMiniColor = NULLHANDLE; HPOINTER hIcon = WinCreatePointerIndirect(HWND_DESKTOP, &info); GpiDeleteBitmap(info.hbmPointer); GpiDeleteBitmap(info.hbmColor); return hIcon; }
static HPOINTER combineTwoCursors(LONG idOver, LONG idUnder) { HPOINTER hptr = NULLHANDLE; POINTERINFO piOver, piUnder; HPOINTER hOver = WinQuerySysPointer(HWND_DESKTOP, idOver, FALSE); WinQueryPointerInfo(hOver, &piOver); HPOINTER hUnder = WinQuerySysPointer(HWND_DESKTOP, idUnder, FALSE); WinQueryPointerInfo(hUnder, &piUnder); if (piOver.hbmColor) { HPS hpsPtr, hpsTmp, hpsMask; HBITMAP hbmPtr, hbmTmp, hbmMask; qt_alloc_ps_with_bitmap(32, 32, false, hpsPtr, hbmPtr); qt_alloc_ps_with_bitmap(32, 32, false, hpsTmp, hbmTmp); qt_alloc_ps_with_bitmap(32, 64, true, hpsMask, hbmMask); // copy the overlying pointer POINTL ptls[] = { { 0, 0 }, { 31, 31 }, { 0, 0 }, { 32, 32 } }; GpiWCBitBlt(hpsTmp, piOver.hbmColor, 4, ptls, ROP_SRCCOPY, BBO_IGNORE); // make its transparent pixels black ptls[2].y += 32; ptls[3].y += 32; GpiSetColor(hpsTmp, CLR_TRUE); GpiSetBackColor(hpsTmp, CLR_FALSE); GpiWCBitBlt(hpsTmp, piOver.hbmPointer, 4, ptls, 0x22, BBO_IGNORE); // copy the underlying pointer ptls[2].y -= 32; ptls[3].y -= 32; GpiWCBitBlt(hpsPtr, piUnder.hbmColor, 4, ptls, ROP_SRCCOPY, BBO_IGNORE); // make non-transparent pixels from the overlying pointer black ptls[2].y += 32; ptls[3].y += 32; GpiSetColor(hpsPtr, CLR_TRUE); GpiSetBackColor(hpsPtr, CLR_FALSE); GpiWCBitBlt(hpsPtr, piOver.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE); // put the overlying pointer there ptls[2].y -= 32; ptls[3].y -= 32; ptls[1].x ++; ptls[1].y ++; GpiBitBlt(hpsPtr, hpsTmp, 4, ptls, ROP_SRCPAINT, BBO_IGNORE); // copy both underlying pointer's masks ptls[1].x --; ptls[1].y --; ptls[1].y += 32; ptls[3].y += 32; GpiWCBitBlt(hpsMask, piUnder.hbmPointer, 4, ptls, ROP_SRCCOPY, BBO_IGNORE); // add overlying pointer's XOR mask ptls[1].y -= 32; ptls[3].y -= 32; GpiWCBitBlt(hpsMask, piOver.hbmPointer, 4, ptls, ROP_SRCPAINT, BBO_IGNORE); // add overlying pointer's AND mask ptls[0].y += 32; ptls[2].y += 32; ptls[1].y += 32; ptls[3].y += 32; GpiWCBitBlt(hpsMask, piOver.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE); // create the new pointer GpiSetBitmap(hpsPtr, NULLHANDLE); GpiSetBitmap(hpsMask, NULLHANDLE); piOver.hbmColor = hbmPtr; piOver.hbmPointer = hbmMask; piOver.hbmMiniColor = NULLHANDLE; piOver.hbmMiniPointer = NULLHANDLE; hptr = WinCreatePointerIndirect(HWND_DESKTOP, &piOver); qt_free_ps_with_bitmap(hpsMask, hbmMask); qt_free_ps_with_bitmap(hpsTmp, hbmTmp); qt_free_ps_with_bitmap(hpsPtr, hbmPtr); } else { HPS hps; HBITMAP hbm; qt_alloc_ps_with_bitmap(32, 64, true, hps, hbm); POINTL ptls[] = { { 0, 0 }, { 31, 63 }, { 0, 0 }, { 32, 64 } }; // make a copy of the underlying pointer GpiWCBitBlt(hps, piUnder.hbmPointer, 4, ptls, ROP_SRCCOPY, BBO_IGNORE); // combine AND masks ptls[0].y += 32; ptls[2].y += 32; GpiWCBitBlt(hps, piOver.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE); // apply the overlying AND mask to the underlying XOR mask ptls[0].y -= 32; ptls[1].y -= 32; GpiWCBitBlt(hps, piOver.hbmPointer, 4, ptls, ROP_SRCAND, BBO_IGNORE); // apply the overlying XOR mask to the underlying XOR mask ptls[2].y -= 32; ptls[3].y -= 32; GpiWCBitBlt(hps, piOver.hbmPointer, 4, ptls, ROP_SRCINVERT, BBO_IGNORE); // create the new pointer GpiSetBitmap(hps, 0); hptr = WinCreatePointer(HWND_DESKTOP, hbm, TRUE, piOver.xHotspot, piOver.yHotspot); qt_free_ps_with_bitmap(hps, hbm); } Q_ASSERT(hptr); return hptr; }