Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Win32 Menu bitmaps

Win32 Menu bitmaps

Scheduled Pinned Locked Moved C / C++ / MFC
dotnetgraphicsperformanceannouncement
8 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • J Offline
    J Offline
    Jonathan Davies
    wrote on last edited by
    #1

    Using an ImageList to load 16 x 16 bitmaps into a toolbar I've been trying to use the bitmaps from that same ImageList for corresponding menu items but I can't get rid of a whiteness around the images. The main code block code below gives the best I can get. Though I can use a IMAGELISTDRAWPARAMS setting the ilDrawParams.rgbBk = GetSysColor(COLOR_MENU) and using ImageList_DrawIndirect which does get rid of the whiteness though the background is then wrong again if the menu item is highlighted - this also seems to be missing the point when is seems the bitmaps can supposedly be drawn transparently anyway. Any suggestions appreciated.

    // Get a menu handle for the one to have an image added to it
    HMENU hMenuMain = GetMenu(hWnd); 
    HMENU hTestMenu = GetSubMenu(hMenuMain, PORT\_MENU\_ID);
    
    // Load the image i.e. a bitmap 'strip' that is actually a number of bitmaps
    HIMAGELIST hImageList = ::ImageList\_LoadImage(hInst, MAKEINTRESOURCE(IDB\_BITMAP1), 16, 0, 
                          RGB(255,0,255), IMAGE\_BITMAP, LR\_SHARED | LR\_LOADTRANSPARENT);
    
    // Get DC for Window client area 
    HDC hDCWindow = ::GetDC(hWnd);
    
    // and create a compatibles DC im memory
    HDC hDCDest = CreateCompatibleDC(hDCWindow);
    
    // Create a bitmap compatible with the device associated with the DC
    HBITMAP hComapatBitmap = CreateCompatibleBitmap(hDCWindow, 16, 16);
    
    // Select the destination bitmap into the DC
    HGDIOBJ hOldDestBmp = SelectObject(hDCDest, hComapatBitmap);
    
    // Bitmap is already selected into a screen-compatible device context by the image list
    BOOL bDrawn = ImageList\_DrawEx(hImageList, 1, hDCDest, 0, 0, 16, 16, RGB(255, 0, 255), 
                                                        CLR\_NONE , ILD\_TRANSPARENT);
    
    // Select back old object back in retrieving returned drawn bitmap
    HBITMAP hRetrievedBitmap = (HBITMAP)::SelectObject(hDCDest, hOldDestBmp);
    
    // as used CreateCompatibleDC(...) must delete it
    ::DeleteDC(hDCDest);
    
    // as used GetDc must release it
    ::ReleaseDC(hWnd, hDCWindow);
    
    // Create a structure that describes the change to make to the menu item  
    MENUITEMINFO MenuItemInfo;
    ::SecureZeroMemory(&MenuItemInfo, sizeof(MENUITEMINFO));
    MenuItemInfo.cbSize = sizeof(MENUITEMINFO);
    
    MenuItemInfo.fMask = MIIM\_BITMAP;
    MenuItemInfo.hbmpItem = hRetrievedBitmap;
    
    // Make the change
    ::SetMenuItemInfo(hTestMenu, ID\_PORT\_E
    
    L P 2 Replies Last reply
    0
    • J Jonathan Davies

      Using an ImageList to load 16 x 16 bitmaps into a toolbar I've been trying to use the bitmaps from that same ImageList for corresponding menu items but I can't get rid of a whiteness around the images. The main code block code below gives the best I can get. Though I can use a IMAGELISTDRAWPARAMS setting the ilDrawParams.rgbBk = GetSysColor(COLOR_MENU) and using ImageList_DrawIndirect which does get rid of the whiteness though the background is then wrong again if the menu item is highlighted - this also seems to be missing the point when is seems the bitmaps can supposedly be drawn transparently anyway. Any suggestions appreciated.

      // Get a menu handle for the one to have an image added to it
      HMENU hMenuMain = GetMenu(hWnd); 
      HMENU hTestMenu = GetSubMenu(hMenuMain, PORT\_MENU\_ID);
      
      // Load the image i.e. a bitmap 'strip' that is actually a number of bitmaps
      HIMAGELIST hImageList = ::ImageList\_LoadImage(hInst, MAKEINTRESOURCE(IDB\_BITMAP1), 16, 0, 
                            RGB(255,0,255), IMAGE\_BITMAP, LR\_SHARED | LR\_LOADTRANSPARENT);
      
      // Get DC for Window client area 
      HDC hDCWindow = ::GetDC(hWnd);
      
      // and create a compatibles DC im memory
      HDC hDCDest = CreateCompatibleDC(hDCWindow);
      
      // Create a bitmap compatible with the device associated with the DC
      HBITMAP hComapatBitmap = CreateCompatibleBitmap(hDCWindow, 16, 16);
      
      // Select the destination bitmap into the DC
      HGDIOBJ hOldDestBmp = SelectObject(hDCDest, hComapatBitmap);
      
      // Bitmap is already selected into a screen-compatible device context by the image list
      BOOL bDrawn = ImageList\_DrawEx(hImageList, 1, hDCDest, 0, 0, 16, 16, RGB(255, 0, 255), 
                                                          CLR\_NONE , ILD\_TRANSPARENT);
      
      // Select back old object back in retrieving returned drawn bitmap
      HBITMAP hRetrievedBitmap = (HBITMAP)::SelectObject(hDCDest, hOldDestBmp);
      
      // as used CreateCompatibleDC(...) must delete it
      ::DeleteDC(hDCDest);
      
      // as used GetDc must release it
      ::ReleaseDC(hWnd, hDCWindow);
      
      // Create a structure that describes the change to make to the menu item  
      MENUITEMINFO MenuItemInfo;
      ::SecureZeroMemory(&MenuItemInfo, sizeof(MENUITEMINFO));
      MenuItemInfo.cbSize = sizeof(MENUITEMINFO);
      
      MenuItemInfo.fMask = MIIM\_BITMAP;
      MenuItemInfo.hbmpItem = hRetrievedBitmap;
      
      // Make the change
      ::SetMenuItemInfo(hTestMenu, ID\_PORT\_E
      
      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      The bitmap needs to contain some indication of transparent background to avoid this problem. I cannot remember exactly how it is identified, but I have a feeling it is some "key" pixel. MSDN or Google may have more information.

      Use the best guess

      J 1 Reply Last reply
      0
      • J Jonathan Davies

        Using an ImageList to load 16 x 16 bitmaps into a toolbar I've been trying to use the bitmaps from that same ImageList for corresponding menu items but I can't get rid of a whiteness around the images. The main code block code below gives the best I can get. Though I can use a IMAGELISTDRAWPARAMS setting the ilDrawParams.rgbBk = GetSysColor(COLOR_MENU) and using ImageList_DrawIndirect which does get rid of the whiteness though the background is then wrong again if the menu item is highlighted - this also seems to be missing the point when is seems the bitmaps can supposedly be drawn transparently anyway. Any suggestions appreciated.

        // Get a menu handle for the one to have an image added to it
        HMENU hMenuMain = GetMenu(hWnd); 
        HMENU hTestMenu = GetSubMenu(hMenuMain, PORT\_MENU\_ID);
        
        // Load the image i.e. a bitmap 'strip' that is actually a number of bitmaps
        HIMAGELIST hImageList = ::ImageList\_LoadImage(hInst, MAKEINTRESOURCE(IDB\_BITMAP1), 16, 0, 
                              RGB(255,0,255), IMAGE\_BITMAP, LR\_SHARED | LR\_LOADTRANSPARENT);
        
        // Get DC for Window client area 
        HDC hDCWindow = ::GetDC(hWnd);
        
        // and create a compatibles DC im memory
        HDC hDCDest = CreateCompatibleDC(hDCWindow);
        
        // Create a bitmap compatible with the device associated with the DC
        HBITMAP hComapatBitmap = CreateCompatibleBitmap(hDCWindow, 16, 16);
        
        // Select the destination bitmap into the DC
        HGDIOBJ hOldDestBmp = SelectObject(hDCDest, hComapatBitmap);
        
        // Bitmap is already selected into a screen-compatible device context by the image list
        BOOL bDrawn = ImageList\_DrawEx(hImageList, 1, hDCDest, 0, 0, 16, 16, RGB(255, 0, 255), 
                                                            CLR\_NONE , ILD\_TRANSPARENT);
        
        // Select back old object back in retrieving returned drawn bitmap
        HBITMAP hRetrievedBitmap = (HBITMAP)::SelectObject(hDCDest, hOldDestBmp);
        
        // as used CreateCompatibleDC(...) must delete it
        ::DeleteDC(hDCDest);
        
        // as used GetDc must release it
        ::ReleaseDC(hWnd, hDCWindow);
        
        // Create a structure that describes the change to make to the menu item  
        MENUITEMINFO MenuItemInfo;
        ::SecureZeroMemory(&MenuItemInfo, sizeof(MENUITEMINFO));
        MenuItemInfo.cbSize = sizeof(MENUITEMINFO);
        
        MenuItemInfo.fMask = MIIM\_BITMAP;
        MenuItemInfo.hbmpItem = hRetrievedBitmap;
        
        // Make the change
        ::SetMenuItemInfo(hTestMenu, ID\_PORT\_E
        
        P Offline
        P Offline
        pasztorpisti
        wrote on last edited by
        #3

        I've never found a good solution to this problem. Maybe the HBMMENU_CALLBACK of Vista solves this (I havent tried it) but even in that case it would push up the minimum OS version requirement of your program without any particular reason. I've solved this problem a few times by using ownerdraw menu items but in that case you have to take care a lot of things even if you ignore the look and feel of the OS: like font sizes, underlining the hotkeys in menu item text... Customizing menu items and rawing their icons nicely is a pain in the ass. I would go with ilDrawParams.rgbBk = GetSysColor(COLOR_MENU). It is not perfect but I wouldn't invest time in owner draw items again for a small cosmetic bug.

        J 2 Replies Last reply
        0
        • P pasztorpisti

          I've never found a good solution to this problem. Maybe the HBMMENU_CALLBACK of Vista solves this (I havent tried it) but even in that case it would push up the minimum OS version requirement of your program without any particular reason. I've solved this problem a few times by using ownerdraw menu items but in that case you have to take care a lot of things even if you ignore the look and feel of the OS: like font sizes, underlining the hotkeys in menu item text... Customizing menu items and rawing their icons nicely is a pain in the ass. I would go with ilDrawParams.rgbBk = GetSysColor(COLOR_MENU). It is not perfect but I wouldn't invest time in owner draw items again for a small cosmetic bug.

          J Offline
          J Offline
          Jonathan Davies
          wrote on last edited by
          #4

          The problem seems to be that the Menu background as obtained by getting MENUINFO.hbrBack isn't the same colour as the menus. I filled my bitmaps that go on the menus with that colour without any icons to see if it all matched. It doesn't, I can see white squares where the icons go against the light blue/grey of the menu (on Windows 8) That white, as seen behind the drawn bitmaps, is presumably what I was trying to remove. I think I'll take your advice leave it as it is. Thanks.

          P 1 Reply Last reply
          0
          • L Lost User

            The bitmap needs to contain some indication of transparent background to avoid this problem. I cannot remember exactly how it is identified, but I have a feeling it is some "key" pixel. MSDN or Google may have more information.

            Use the best guess

            J Offline
            J Offline
            Jonathan Davies
            wrote on last edited by
            #5

            Richard, Thanks for the hint, but (as explained below) the problem seems to be with the obtained menu background (white)not being the same colour as the menu (light blue/grey). Thanks anyway.

            1 Reply Last reply
            0
            • J Jonathan Davies

              The problem seems to be that the Menu background as obtained by getting MENUINFO.hbrBack isn't the same colour as the menus. I filled my bitmaps that go on the menus with that colour without any icons to see if it all matched. It doesn't, I can see white squares where the icons go against the light blue/grey of the menu (on Windows 8) That white, as seen behind the drawn bitmaps, is presumably what I was trying to remove. I think I'll take your advice leave it as it is. Thanks.

              P Offline
              P Offline
              pasztorpisti
              wrote on last edited by
              #6

              I'm still stuck on win7 but I guess what you mean. Since WinXP there are several window managers (like aero, xp-style, old-school,...) and some of these are using extra colors besides the old-school window manager for which the old API was engineered. Sometimes the api lies to your program depending on windows version compatibility settings and the manifest you put into your program. I wouldn't be surprised if there were some fancy APIs to query the REAL colors in another way or with different constants from a newer SDK but I avoided making headaches for myself by polishing GUIs with WinAPI in the last few years... :-) I guess you have better things to do and customizing the menus is one particular thing that really sucks. In my opinion most of the winapi controls, especially the older ones (including menus) are not good candidates for customization. Things could be worse only if you wanted to customize the menu borders: I've seen code that handled undocumented mouse messages and installed cbt hooks - made me sick and I always started vomiting while reading it... Once I was dreaming about creating a gui skinner lib but I got bored of it halfway when I got to know the sad truth and the mountain of hacks involved...

              1 Reply Last reply
              0
              • P pasztorpisti

                I've never found a good solution to this problem. Maybe the HBMMENU_CALLBACK of Vista solves this (I havent tried it) but even in that case it would push up the minimum OS version requirement of your program without any particular reason. I've solved this problem a few times by using ownerdraw menu items but in that case you have to take care a lot of things even if you ignore the look and feel of the OS: like font sizes, underlining the hotkeys in menu item text... Customizing menu items and rawing their icons nicely is a pain in the ass. I would go with ilDrawParams.rgbBk = GetSysColor(COLOR_MENU). It is not perfect but I wouldn't invest time in owner draw items again for a small cosmetic bug.

                J Offline
                J Offline
                Jonathan Davies
                wrote on last edited by
                #7

                Read the MSDN stuff again and found I should have been using GetSysColorBrush(COLOR_MENU); rather then the GetSysColor(COLOR_MENU); I was using which apparently 'returns a cached brush, instead of allocating a new one'. This now does the correct menu background colour. Could explain why GetSysColor(COLOR_MENU); worked yesterday and not today.

                P 1 Reply Last reply
                0
                • J Jonathan Davies

                  Read the MSDN stuff again and found I should have been using GetSysColorBrush(COLOR_MENU); rather then the GetSysColor(COLOR_MENU); I was using which apparently 'returns a cached brush, instead of allocating a new one'. This now does the correct menu background colour. Could explain why GetSysColor(COLOR_MENU); worked yesterday and not today.

                  P Offline
                  P Offline
                  pasztorpisti
                  wrote on last edited by
                  #8

                  Thanks for the info! We learn something new every day... :-)

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups