diff --git a/code/nel/include/nel/3d/driver.h b/code/nel/include/nel/3d/driver.h index 6428baab5..2a0d061fd 100644 --- a/code/nel/include/nel/3d/driver.h +++ b/code/nel/include/nel/3d/driver.h @@ -186,6 +186,9 @@ public: /// Set the title of the NeL window virtual void setWindowTitle(const ucstring &title)=0; + /// Set icon(s) of the NeL window + virtual void setWindowIcon(const std::vector &bitmaps)=0; + /// Set the position of the NeL window virtual void setWindowPos(sint32 x, sint32 y)=0; diff --git a/code/nel/include/nel/3d/driver_user.h b/code/nel/include/nel/3d/driver_user.h index 1bda23c27..699691d89 100644 --- a/code/nel/include/nel/3d/driver_user.h +++ b/code/nel/include/nel/3d/driver_user.h @@ -148,6 +148,9 @@ public: /// Set the title of the NeL window virtual void setWindowTitle(const ucstring &title); + /// Set icon(s) of the NeL window + virtual void setWindowIcon(const std::vector &bitmaps); + /// Set the position of the NeL window virtual void setWindowPos(sint32 x, sint32 y); diff --git a/code/nel/include/nel/3d/ps_color.h b/code/nel/include/nel/3d/ps_color.h index 1c52d68e4..a46e2122a 100644 --- a/code/nel/include/nel/3d/ps_color.h +++ b/code/nel/include/nel/3d/ps_color.h @@ -34,7 +34,7 @@ namespace NL3D { template <> -const char *CPSAttribMaker::getType() { return "CRGBA"; } +inline const char *CPSAttribMaker::getType() { return "CRGBA"; } // Depending on the driver, the format of colors in vertex buffer may change. We don't want to change the format for each data that is (dynamically) in vertex buffer, so diff --git a/code/nel/include/nel/3d/ps_float.h b/code/nel/include/nel/3d/ps_float.h index 20878de27..8dcc732aa 100644 --- a/code/nel/include/nel/3d/ps_float.h +++ b/code/nel/include/nel/3d/ps_float.h @@ -28,7 +28,7 @@ namespace NL3D { template <> -const char *CPSAttribMaker::getType() { return "float"; } +inline const char *CPSAttribMaker::getType() { return "float"; } /// these are some attribute makers for float /// This is a float blender class. It just blend between 2 values diff --git a/code/nel/include/nel/3d/ps_int.h b/code/nel/include/nel/3d/ps_int.h index 1985ec6d7..d821ad7b9 100644 --- a/code/nel/include/nel/3d/ps_int.h +++ b/code/nel/include/nel/3d/ps_int.h @@ -26,7 +26,7 @@ namespace NL3D { template <> -const char *CPSAttribMaker::getType() { return "int32"; } +inline const char *CPSAttribMaker::getType() { return "int32"; } /// these are some attribute makers for int diff --git a/code/nel/include/nel/3d/ps_plane_basis_maker.h b/code/nel/include/nel/3d/ps_plane_basis_maker.h index b7ae6de29..51714a368 100644 --- a/code/nel/include/nel/3d/ps_plane_basis_maker.h +++ b/code/nel/include/nel/3d/ps_plane_basis_maker.h @@ -28,7 +28,7 @@ namespace NL3D { template <> -const char *CPSAttribMaker::getType() { return "CPlaneBasis";} +inline const char *CPSAttribMaker::getType() { return "CPlaneBasis";} /** these are some attribute makers for plane_basis * This is a plane basis class. It just blend between 2 plane by linearly interpolating the normal diff --git a/code/nel/include/nel/3d/u_driver.h b/code/nel/include/nel/3d/u_driver.h index 4e7b2eb05..ce421b46d 100644 --- a/code/nel/include/nel/3d/u_driver.h +++ b/code/nel/include/nel/3d/u_driver.h @@ -186,6 +186,9 @@ public: /// Set the title of the NeL window virtual void setWindowTitle(const ucstring &title)=0; + /// Set icon(s) of the NeL window + virtual void setWindowIcon(const std::vector &bitmaps)=0; + /// Set the position of the NeL window virtual void setWindowPos(sint32 x, sint32 y)=0; diff --git a/code/nel/include/nel/misc/bitmap.h b/code/nel/include/nel/misc/bitmap.h index 99fa5527f..2a2361b55 100644 --- a/code/nel/include/nel/misc/bitmap.h +++ b/code/nel/include/nel/misc/bitmap.h @@ -621,6 +621,10 @@ public: void getDibData(uint8*& extractData); +#ifdef NL_OS_WINDOWS + HICON getHICON(sint iconWidth, sint iconHeight, sint iconDepth, const NLMISC::CRGBA &col = NLMISC::CRGBA::White, sint hotSpotX = 0, sint hotSpotY = 0, bool cursor = false) const; +#endif + CBitmap& operator= (const CBitmap& from) { if (&from == this) diff --git a/code/nel/src/3d/driver.cpp b/code/nel/src/3d/driver.cpp index d8a195c3a..39d72c7c3 100644 --- a/code/nel/src/3d/driver.cpp +++ b/code/nel/src/3d/driver.cpp @@ -34,7 +34,7 @@ namespace NL3D { // *************************************************************************** -const uint32 IDriver::InterfaceVersion = 0x67; // changed window pos from uint32 to sint32 +const uint32 IDriver::InterfaceVersion = 0x68; // added setWindowIcon // *************************************************************************** IDriver::IDriver() : _SyncTexDrvInfos( "IDriver::_SyncTexDrvInfos" ) diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp index 3986e8e26..e096a4d00 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.cpp @@ -1712,6 +1712,10 @@ bool CDriverD3D::release() if (_HWnd) { + // make sure window icons are deleted + std::vector bitmaps; + setWindowIcon(bitmaps); + if (_DestroyWindow) DestroyWindow (_HWnd); _HWnd = NULL; @@ -2177,6 +2181,73 @@ void CDriverD3D::setWindowTitle(const ucstring &title) SetWindowTextW(_HWnd,(WCHAR*)title.c_str()); } +// *************************************************************************** +void CDriverD3D::setWindowIcon(const std::vector &bitmaps) +{ + if (!_HWnd) + return; + + static HICON winIconBig = NULL; + static HICON winIconSmall = NULL; + + if (winIconBig) + { + DestroyIcon(winIconBig); + winIconBig = NULL; + } + + if (winIconSmall) + { + DestroyIcon(winIconSmall); + winIconSmall = NULL; + } + + sint smallIndex = -1; + uint smallWidth = GetSystemMetrics(SM_CXSMICON); + uint smallHeight = GetSystemMetrics(SM_CYSMICON); + + sint bigIndex = -1; + uint bigWidth = GetSystemMetrics(SM_CXICON); + uint bigHeight = GetSystemMetrics(SM_CYICON); + + // find icons with the exact size + for(uint i = 0; i < bitmaps.size(); ++i) + { + if (smallIndex == -1 && bitmaps[i].getWidth() == smallWidth && bitmaps[i].getHeight() == smallHeight) + smallIndex = i; + + if (bigIndex == -1 && bitmaps[i].getWidth() == bigWidth && bitmaps[i].getHeight() == bigHeight) + bigIndex = i; + } + + // find icons with taller size (we will resize them) + for(uint i = 0; i < bitmaps.size(); ++i) + { + if (smallIndex == -1 && bitmaps[i].getWidth() >= smallWidth && bitmaps[i].getHeight() >= smallHeight) + smallIndex = i; + + if (bigIndex == -1 && bitmaps[i].getWidth() >= bigWidth && bitmaps[i].getHeight() >= bigHeight) + bigIndex = i; + } + + if (smallIndex > -1) + winIconSmall = bitmaps[smallIndex].getHICON(smallWidth, smallHeight, 32); + + if (bigIndex > -1) + winIconBig = bitmaps[bigIndex].getHICON(bigWidth, bigHeight, 32); + + if (winIconBig) + { + SendMessage(_HWnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)winIconSmall); + SendMessage(_HWnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)winIconBig); + } + else + { + SendMessage(_HWnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)winIconSmall); + SendMessage(_HWnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)winIconSmall); + } +} + // *************************************************************************** void CDriverD3D::setWindowPos(sint32 x, sint32 y) { diff --git a/code/nel/src/3d/driver/direct3d/driver_direct3d.h b/code/nel/src/3d/driver/direct3d/driver_direct3d.h index 52dca1dc5..ccd414782 100644 --- a/code/nel/src/3d/driver/direct3d/driver_direct3d.h +++ b/code/nel/src/3d/driver/direct3d/driver_direct3d.h @@ -759,6 +759,9 @@ public: /// Set the title of the NeL window virtual void setWindowTitle(const ucstring &title); + /// Set icon(s) of the NeL window + virtual void setWindowIcon(const std::vector &bitmaps); + /// Set the position of the NeL window virtual void setWindowPos(sint32 x, sint32 y); diff --git a/code/nel/src/3d/driver/opengl/driver_opengl.h b/code/nel/src/3d/driver/opengl/driver_opengl.h index 44ce39c2c..18397d61b 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl/driver_opengl.h @@ -294,10 +294,13 @@ public: virtual void beginDialogMode(); virtual void endDialogMode(); - /// Set the title of the NeL window + /// Set title of the NeL window virtual void setWindowTitle(const ucstring &title); - /// Set the position of the NeL window + /// Set icon(s) of the NeL window + virtual void setWindowIcon(const std::vector &bitmaps); + + /// Set position of the NeL window virtual void setWindowPos(sint32 x, sint32 y); /// Show or hide the NeL window diff --git a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp index acc84ef13..3fecf8188 100644 --- a/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/code/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -35,11 +35,13 @@ # ifdef XRANDR # include # endif +# include #endif // NL_OS_UNIX #include "nel/misc/mouse_device.h" #include "nel/misc/di_event_emitter.h" #include "nel/3d/u_driver.h" +#include "nel/misc/file.h" using namespace std; using namespace NLMISC; @@ -296,6 +298,123 @@ bool CDriverGL::unInit() return true; } +void CDriverGL::setWindowIcon(const std::vector &bitmaps) +{ + if (_win == EmptyWindow) + return; + +#if defined(NL_OS_WINDOWS) + + static HICON winIconBig = NULL; + static HICON winIconSmall = NULL; + + if (winIconBig) + { + DestroyIcon(winIconBig); + winIconBig = NULL; + } + + if (winIconSmall) + { + DestroyIcon(winIconSmall); + winIconSmall = NULL; + } + + sint smallIndex = -1; + uint smallWidth = GetSystemMetrics(SM_CXSMICON); + uint smallHeight = GetSystemMetrics(SM_CYSMICON); + + sint bigIndex = -1; + uint bigWidth = GetSystemMetrics(SM_CXICON); + uint bigHeight = GetSystemMetrics(SM_CYICON); + + // find icons with the exact size + for(uint i = 0; i < bitmaps.size(); ++i) + { + if (smallIndex == -1 && bitmaps[i].getWidth() == smallWidth && bitmaps[i].getHeight() == smallHeight) + smallIndex = i; + + if (bigIndex == -1 && bitmaps[i].getWidth() == bigWidth && bitmaps[i].getHeight() == bigHeight) + bigIndex = i; + } + + // find icons with taller size (we will resize them) + for(uint i = 0; i < bitmaps.size(); ++i) + { + if (smallIndex == -1 && bitmaps[i].getWidth() >= smallWidth && bitmaps[i].getHeight() >= smallHeight) + smallIndex = i; + + if (bigIndex == -1 && bitmaps[i].getWidth() >= bigWidth && bitmaps[i].getHeight() >= bigHeight) + bigIndex = i; + } + + if (smallIndex > -1) + winIconSmall = bitmaps[smallIndex].getHICON(smallWidth, smallHeight, 32); + + if (bigIndex > -1) + winIconBig = bitmaps[bigIndex].getHICON(bigWidth, bigHeight, 32); + + if (winIconBig) + { + SendMessage(_win, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)winIconSmall); + SendMessage(_win, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)winIconBig); + } + else + { + SendMessage(_win, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)winIconSmall); + SendMessage(_win, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)winIconSmall); + } + +#elif defined(NL_OS_MAC) + + // nothing to do + +#elif defined(NL_OS_UNIX) + + std::vector icon_data; + + if (!bitmaps.empty()) + { + // process each bitmap + for(uint i = 0; i < bitmaps.size(); ++i) + { + // get bitmap width and height + uint width = bitmaps[i].getWidth(); + uint height = bitmaps[i].getHeight(); + + // icon_data position for bitmap + uint pos = (uint)icon_data.size(); + + // extend icon_data size for bitmap + icon_data.resize(pos + 2 + width*height); + + // set bitmap width and height + icon_data[pos++] = width; + icon_data[pos++] = height; + + // convert RGBA to ARGB + CObjectVector pixels = bitmaps[i].getPixels(); + for(uint j = 0; j < pixels.size(); j+=4) + icon_data[pos++] = pixels[j] << 16 | pixels[j+1] << 8 | pixels[j+2] | pixels[j+3] << 24; + } + } + + Atom _NET_WM_ICON = XInternAtom(_dpy, "_NET_WM_ICON", False); + + if (!icon_data.empty()) + { + // change window icon + XChangeProperty(_dpy, _win, _NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (const unsigned char *) &icon_data[0], icon_data.size()); + } + else + { + // delete window icon if no bitmap is available + XDeleteProperty(_dpy, _win, _NET_WM_ICON); + } + +#endif // NL_OS_WINDOWS +} + // -------------------------------------------------- bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool resizeable) throw(EBadDisplay) { @@ -967,7 +1086,7 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) if (ChangeDisplaySettings(&devMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { - nlwarning("Fullscreen mode switch failed"); + nlwarning("3D: Fullscreen mode switch failed"); return false; } @@ -1135,6 +1254,10 @@ bool CDriverGL::destroyWindow() { H_AUTO_OGL(CDriverGL_destroyWindow) + // make sure window icons are deleted + std::vector bitmaps; + setWindowIcon(bitmaps); + #ifdef NL_OS_WINDOWS // Then delete. diff --git a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm index aa0cf9dbb..9ad145e1b 100644 --- a/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm +++ b/code/nel/src/3d/driver/opengl/mac/cocoa_adapter.mm @@ -809,49 +809,46 @@ void submitEvents(NLMISC::CEventServer& server, continue; } + // convert the modifiers for nel to pass them with the events + NLMISC::TKeyButton modifiers = + modifierFlagsToNelKeyButton([event modifierFlags]); + switch(event.type) { case NSLeftMouseDown: { - /* - TODO modifiers with mouse events - */ server.postEvent(new NLMISC::CEventMouseDown( - mouseX, mouseY, NLMISC::leftButton /* modifiers */, eventEmitter)); + mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), + eventEmitter)); } break; case NSLeftMouseUp: { - /* - TODO modifiers with mouse events - */ server.postEvent(new NLMISC::CEventMouseUp( - mouseX, mouseY, NLMISC::leftButton /* modifiers */, eventEmitter)); + mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), + eventEmitter)); break; } case NSRightMouseDown: { - /* - TODO modifiers with mouse events - */ server.postEvent(new NLMISC::CEventMouseDown( - mouseX, mouseY, NLMISC::rightButton /* modifiers */, eventEmitter)); + mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), + eventEmitter)); break; } case NSRightMouseUp: { - /* - TODO modifiers with mouse events - */ server.postEvent(new NLMISC::CEventMouseUp( - mouseX, mouseY, NLMISC::rightButton /* modifiers */, eventEmitter)); + mouseX, mouseY, + (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), + eventEmitter)); break; } case NSMouseMoved: { - /* - TODO modifiers with mouse events - */ NLMISC::CEvent* nelEvent; // when emulating raw mode, send the delta in a CGDMouseMove event @@ -861,17 +858,14 @@ void submitEvents(NLMISC::CEventServer& server, // normally send position in a CEventMouseMove else - nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, - (NLMISC::TMouseButton)0 /* modifiers */, eventEmitter); + nelEvent = new NLMISC::CEventMouseMove( + mouseX, mouseY, (NLMISC::TMouseButton)modifiers, eventEmitter); server.postEvent(nelEvent); break; } case NSLeftMouseDragged: { - /* - TODO modifiers with mouse events - */ NLMISC::CEvent* nelEvent; // when emulating raw mode, send the delta in a CGDMouseMove event @@ -882,16 +876,14 @@ void submitEvents(NLMISC::CEventServer& server, // normally send position in a CEventMouseMove else nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, - NLMISC::leftButton /* modifiers */, eventEmitter); + (NLMISC::TMouseButton)(NLMISC::leftButton | modifiers), + eventEmitter); server.postEvent(nelEvent); break; } case NSRightMouseDragged: { - /* - TODO modifiers with mouse events - */ NLMISC::CEvent* nelEvent; // when emulating raw mode, send the delta in a CGDMouseMove event @@ -902,7 +894,8 @@ void submitEvents(NLMISC::CEventServer& server, // normally send position in a CEventMouseMove else nelEvent = new NLMISC::CEventMouseMove(mouseX, mouseY, - NLMISC::rightButton /* modifiers */, eventEmitter); + (NLMISC::TMouseButton)(NLMISC::rightButton | modifiers), + eventEmitter); server.postEvent(nelEvent); break; @@ -951,12 +944,9 @@ void submitEvents(NLMISC::CEventServer& server, case NSCursorUpdate:break; case NSScrollWheel: { - /* - TODO modifiers with mouse events - */ if(fabs(event.deltaY) > 0.1) server.postEvent(new NLMISC::CEventMouseWheel( - mouseX, mouseY, (NLMISC::TMouseButton)0 /* modifiers */, + mouseX, mouseY, (NLMISC::TMouseButton)modifiers, (event.deltaY > 0), eventEmitter)); break; diff --git a/code/nel/src/3d/driver_user.cpp b/code/nel/src/3d/driver_user.cpp index ea8a44e83..523aaf4ba 100644 --- a/code/nel/src/3d/driver_user.cpp +++ b/code/nel/src/3d/driver_user.cpp @@ -332,6 +332,13 @@ void CDriverUser::setWindowTitle(const ucstring &title) _Driver->setWindowTitle(title); } +// *************************************************************************** +void CDriverUser::setWindowIcon(const std::vector &bitmaps) +{ + NL3D_HAUTO_UI_DRIVER; + _Driver->setWindowIcon(bitmaps); +} + // *************************************************************************** void CDriverUser::setWindowPos(sint32 x, sint32 y) { diff --git a/code/nel/src/misc/bitmap.cpp b/code/nel/src/misc/bitmap.cpp index 09631bb6b..4a97a004d 100644 --- a/code/nel/src/misc/bitmap.cpp +++ b/code/nel/src/misc/bitmap.cpp @@ -1500,7 +1500,7 @@ uint32 CBitmap::getHeight(uint32 mipMap) const /*-------------------------------------------------------------------*\ - getHeight + getSize \*-------------------------------------------------------------------*/ uint32 CBitmap::getSize(uint32 numMipMap) const { @@ -4107,5 +4107,84 @@ void CBitmap::getDibData(uint8*& extractData) } +#ifdef NL_OS_WINDOWS + +HICON CBitmap::getHICON(sint iconWidth, sint iconHeight, sint iconDepth, const NLMISC::CRGBA &col, sint hotSpotX, sint hotSpotY, bool cursor) const +{ + HICON result = NULL; + CBitmap src = *this; + // resample bitmap if necessary + if (_Width != iconWidth || _Height != iconHeight) + { + src.resample(iconWidth, iconHeight); + } + CBitmap colorBm; + colorBm.resize(iconWidth, iconHeight, CBitmap::RGBA); + const CRGBA *srcColorPtr = (CRGBA *) &(src.getPixels()[0]); + const CRGBA *srcColorPtrLast = srcColorPtr + (iconWidth * iconHeight); + CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]); + static volatile uint8 alphaThreshold = 127; + do + { + destColorPtr->modulateFromColor(*srcColorPtr, col); + std::swap(destColorPtr->R, destColorPtr->B); + ++ srcColorPtr; + ++ destColorPtr; + } + while (srcColorPtr != srcColorPtrLast); + // + HBITMAP colorHbm = NULL; + HBITMAP maskHbm = NULL; + // + if (iconDepth == 16) + { + std::vector colorBm16(iconWidth * iconHeight); + const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0]; + + for (uint k = 0; k < colorBm16.size(); ++k) + { + colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8); + } + + colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 16, &colorBm16[0]); + std::vector bitMask((iconWidth * iconHeight + 7) / 8, 0); + + for (uint k = 0;k < colorBm16.size(); ++k) + { + if (src32[k].A <= 120) + { + bitMask[k / 8] |= (0x80 >> (k & 7)); + } + } + + maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 1, &bitMask[0]); + } + else + { + colorHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]); + maskHbm = CreateBitmap(iconWidth, iconHeight, 1, 32, &colorBm.getPixels(0)[0]); + } + + ICONINFO iconInfo; + iconInfo.fIcon = cursor ? FALSE:TRUE; + iconInfo.xHotspot = (DWORD) hotSpotX; + iconInfo.yHotspot = (DWORD) hotSpotY; + iconInfo.hbmMask = maskHbm; + iconInfo.hbmColor = colorHbm; + + if (colorHbm && maskHbm) + { + result = CreateIconIndirect(&iconInfo); + } + + // + if (colorHbm) DeleteObject(colorHbm); + if (maskHbm) DeleteObject(maskHbm); + + return result; +} + +#endif + } // NLMISC diff --git a/code/ryzom/client/src/interface_v3/custom_mouse.cpp b/code/ryzom/client/src/interface_v3/custom_mouse.cpp index af1bb7209..c7d127803 100644 --- a/code/ryzom/client/src/interface_v3/custom_mouse.cpp +++ b/code/ryzom/client/src/interface_v3/custom_mouse.cpp @@ -370,7 +370,6 @@ HICON CCustomMouse::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot uint mouseH = GetSystemMetrics(SM_CYCURSOR); nlassert(src.getWidth() == mouseW); nlassert(src.getHeight() == mouseH); - HICON result = 0; CBitmap rotSrc = src; if (rot > 3) rot = 3; // mimic behavior of 'CViewRenderer::drawRotFlipBitmapTiled' (why not rot & 3 ??? ...) switch(rot) @@ -380,62 +379,7 @@ HICON CCustomMouse::buildCursor(const CBitmap &src, NLMISC::CRGBA col, uint8 rot case 2: rotSrc.rot90CW(); rotSrc.rot90CW(); break; case 3: rotSrc.rot90CCW(); break; } - CBitmap colorBm; - colorBm.resize(mouseW, mouseH, CBitmap::RGBA); - const CRGBA *srcColorPtr = (CRGBA *) &(rotSrc.getPixels()[0]); - const CRGBA *srcColorPtrLast = srcColorPtr + (mouseW * mouseH); - CRGBA *destColorPtr = (CRGBA *) &(colorBm.getPixels()[0]); - static volatile uint8 alphaThreshold = 127; - do - { - destColorPtr->modulateFromColor(*srcColorPtr, col); - std::swap(destColorPtr->R, destColorPtr->B); - ++ srcColorPtr; - ++ destColorPtr; - } - while (srcColorPtr != srcColorPtrLast); - // - HBITMAP colorHbm = 0; - HBITMAP maskHbm = 0; - // - if (_ColorDepth == ColorDepth16) - { - std::vector colorBm16(colorBm.getWidth() * colorBm.getHeight()); - const CRGBA *src32 = (const CRGBA *) &colorBm.getPixels(0)[0]; - for (uint k = 0;k < colorBm16.size(); ++k) - { - colorBm16[k] = ((uint16)(src32[k].R&0xf8)>>3) | ((uint16)(src32[k].G&0xfc)<<3) | ((uint16)(src32[k].B & 0xf8)<<8); - } - colorHbm = CreateBitmap(mouseW, mouseH, 1, 16, &colorBm16[0]); - std::vector bitMask((colorBm.getWidth() * colorBm.getHeight() + 7) / 8, 0); - for (uint k = 0;k < colorBm16.size(); ++k) - { - if (src32[k].A <= 120) - { - bitMask[k / 8] |= (0x80 >> (k & 7)); - } - } - maskHbm = CreateBitmap(mouseW, mouseH, 1, 1, &bitMask[0]); - } - else - { - colorHbm = CreateBitmap(mouseW, mouseH, 1, 32, &colorBm.getPixels(0)[0]); - maskHbm = CreateBitmap(mouseW, mouseH, 1, 32, &colorBm.getPixels(0)[0]); - } - ICONINFO iconInfo; - iconInfo.fIcon = FALSE; - iconInfo.xHotspot = (DWORD) hotSpotX; - iconInfo.yHotspot = (DWORD) hotSpotY; - iconInfo.hbmMask = maskHbm; - iconInfo.hbmColor = colorHbm; - if (colorHbm && maskHbm) - { - result = CreateIconIndirect(&iconInfo); - } - // - if (colorHbm) DeleteObject(colorHbm); - if (maskHbm) DeleteObject(maskHbm); - return result; + return rotSrc.getHICON(mouseW, mouseH, _ColorDepth == ColorDepth16 ? 16:32, col, hotSpotX, hotSpotY, true); }