• Welcome to PlanetSquires Forums.
 

WinFBE using CWindow

Started by Paul Squires, May 28, 2016, 02:44:45 PM

Previous topic - Next topic

José Roca

I'm using only one set of icons.

For the gray images, I use:


i = ImageList_ReplaceIcon(hImageListDisabled, -1, AfxGdipIconFromRes(hInst, "IMAGE_NEW_FILE", 10, TRUE))
[code]

Where 10 is the porcentage of dimming (from 0 to 99) and TRUE indicates conversion to gray.

José Roca

#16
Please check if this menu looks right in your system.

Paul Squires

When you use:
   i = ImageList_ReplaceIcon(hImageListNormal, -1, AfxGdipIconFromRes(hInst, "IMAGE_COMMENT_REMOVE"))

Does the handle returned by AfxGdipIconFromRes have to be explicitly freed/destroyed? In my code using LoadImage, Windows would free the handle so I didn't have to do anything. I wonder does ImageList_ReplaceIcon use the handle you return or does it make a copy of the image a second time for its own use?
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

Paul Squires

Quote from: Jose Roca on May 28, 2016, 09:49:36 PM
Please check if this menu looks right in your system.

It looks okay (but not great) see attached. It does not seem as sharp as yours. Maybe because you are using a much higher DPI than I am.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

> It looks okay (but not great) see attached. It does not seem as sharp as yours. Maybe because you are using a much higher DPI than I am.

Must be because I'm using 48 bit icons that are the ones that I have at hand. Maybe for menus we must use smaller icons.

José Roca

But what I wanted to know is if the problem with the menu using your editor icons was general or just because the icons are only 256 colors.

The menus use PARGB32 bitmaps.

The requirements are:

- The bitmap is a 32bpp DIB section.
- The DIB section has BI_RGB compression.
- The bitmap contains pre-multiplied alpha pixels.

My functions convert the PNG icons to PARGB32 bitmaps.

José Roca

Maybe we may need two use at least two sets of icons, one for 96 to 144 and another for the rest. What we dont need is to have gray icons, because my functions allow to make them on the fly.

Of course, for best quality, nothing like using the appropriate icon size.

José Roca

Quote from: TechSupport on May 28, 2016, 09:56:26 PM
When you use:
   i = ImageList_ReplaceIcon(hImageListNormal, -1, AfxGdipIconFromRes(hInst, "IMAGE_COMMENT_REMOVE"))

Does the handle returned by AfxGdipIconFromRes have to be explicitly freed/destroyed? In my code using LoadImage, Windows would free the handle so I didn't have to do anything. I wonder does ImageList_ReplaceIcon use the handle you return or does it make a copy of the image a second time for its own use?

The MSDN documentations says

Quote
Because the system does not save hicon, you can destroy it after the function returns if the icon or cursor was created by the CreateIcon function. You do not need to destroy hicon if it was loaded by the LoadIcon function; the system automatically frees an icon resource when it is no longer needed.

Since we are creating the icon with GdipCreateHICONFromBitmap, not loading an existing one, guess that to be safe we can destroy it.

José Roca

To avoid flicker, you can disable background erasing with:


   '  Create the main window and child controls
   Dim pWindow As CWindow
   ' // Disable background erasing
   pWindow.ClassStyle = CS_DBLCLKS
   ' // Retrieve the size of the working area
   DIM rc AS RECT = pWindow.GetWorkArea
   pWindow.Create(Null, "WinFBE - FreeBASIC Programmer's Editor", @frmMain_WndProc, _
      0, 0, rc.Right - rc.Left, rc.Bottom - rc.Top)


José Roca

#24
I have modified the menu test to use 32 bit icons for the menu. Looks great in my system (at 192 DPI, 32 bit is the appropriate size). Don't know how will look in yours.

If it does not scale well, then we may need to use several icon sets of different sizes.

Of course this has nothing to do with regard to which icons you use in the editor (I'm not very picky about cosmetic details), but about exploring the best way to deal with the problem of icons size in toolbars, menus and other controls at different DPIs. Indeed, the best way is to use several sets of icons of different sizes, but I was trying to avoid this bloat.

José Roca

#25
Regarding the icons added to menis, you don't need to destroy them unless you specify FALSE in the fAutoDestroy parameter of the AfxAddIconToMenuItem.

If you look at the code of the AfxAddIconToMenuItem function you will see that the optional fAutoDestroy parameter defaults to TRUE and at the end of the function there is the following instruction: IF fAutoDestroy THEN DestroyIcon(hIcon).


' ========================================================================================
' Converts a hIcon to a bitmap and adds it to the specified hbmpItem field of HMENU item.
' The caller is responsible for destroying the bitmap generated. The icon will be destroyed
' if fAutoDestroy is set to true. The hbmpItem field of the menu item can be used to keep
' track of the bitmap by passing NULL to phbmp.
' Parameters:
' - hMenu        = Menu handle that contains the item to which an icon will be added.
' - uItem        = The identifier or position of the menu item to change.
'                  The meaning of this parameter depends on the value of fByPosition.
' - fByPosition  = The meaning of nMenuItem. If this parameter is FALSE, nMenuItem is a
'                  menu item identifier. Otherwise, it is a menu item position.
' - hIcon        = Handle of the icon to add to the menu.
' - fAutoDestroy = TRUE (the default) or FALSE.
'                  If TRUE, AddIconToMenuItem destroys the icon before returning.
' - phbmp        = Location where the bitmap representation of the icon is stored. Can be NULL.
' ========================================================================================
#if _WIN32_WINNT = &h0602
PRIVATE FUNCTION AfxAddIconToMenuItem (BYVAL hMenu AS HMENU, BYVAL uItem AS DWORD, BYVAL fByPosition AS BOOLEAN, BYVAL hIcon AS HICON, BYVAL fAutoDestroy AS BOOLEAN = TRUE, BYVAL phbmp AS HBITMAP PTR = NULL) AS BOOLEAN
   IF hMenu = NULL OR hIcon = NULL THEN EXIT FUNCTION
   DIM hbmp AS HBITMAP, sizIcon AS SIZE, rcIcon AS RECT
   sizIcon.cx = GetSystemMetrics(SM_CXSMICON)
   sizIcon.cy = GetSystemMetrics(SM_CYSMICON)
   SetRect(@rcIcon, 0, 0, sizIcon.cx, sizIcon.cy)
   DIM hdcDest AS HDC = CreateCompatibleDC(NULL)
   IF hdcDest = NULL THEN EXIT FUNCTION
   DIM hr AS LONG = (AfxCreate32BitHBITMAP(hdcDest, @sizIcon, NULL, @hbmp))
   IF hr THEN
      DIM hbmpOld AS HBITMAP = CAST(HBITMAP, SelectObject(hdcDest, hbmp))
      IF hbmpOld THEN
         DIM bfAlpha AS BLENDFUNCTION = (AC_SRC_OVER, 0, 255, AC_SRC_ALPHA)
         DIM paintParams AS BP_PAINTPARAMS
         paintParams.cbSize = SIZEOF(paintParams)
         paintParams.dwFlags = BPPF_ERASE
         paintParams.pBlendFunction = @bfAlpha
         DIM hdcBuffer AS HDC
         DIM hPaintBuffer AS HPAINTBUFFER = BeginBufferedPaint(hdcDest, @rcIcon, BPBF_DIB, @paintParams, @hdcBuffer)
         IF hPaintBuffer THEN
            IF DrawIconEx(hdcBuffer, 0, 0, hIcon, sizIcon.cx, sizIcon.cy, 0, NULL, DI_NORMAL) THEN
               ' // If icon did not have an alpha channel, we need to convert buffer to PARGB32.
               hr = AfxConvertBufferToPARGB32(hPaintBuffer, hdcDest, hIcon, sizIcon)
            END IF
            ' // This will write the buffer contents to the destination bitmap.
            EndBufferedPaint(hPaintBuffer, TRUE)
         END IF
         SelectObject(hdcDest, hbmpOld)
      END IF
   END IF
   DeleteDC(hdcDest)
   IF hr THEN hr = AfxAddBitmapToMenuItem(hMenu, uItem, fByPosition, hbmp)
   IF hr = FALSE THEN DeleteObject(hbmp): hbmp = NULL
   IF fAutoDestroy THEN DestroyIcon(hIcon)
   IF phbmp THEN *phbmp = hbmp
   FUNCTION = hr
END FUNCTION
#endif
' ========================================================================================


José Roca

> Does the handle returned by AfxGdipIconFromRes have to be explicitly freed/destroyed?

A solution would be to write a function called AfxImageListReplaceIcon with an optional fAutoDestroy parameter like the one for menus.


José Roca

See http://www.planetsquires.com/protect/forum/index.php?topic=3838.new#new

With the new functions, instead of


ImageList_ReplaceIcon(hImageList, -1, AfxGdipIconFromFile(ExePath & "\arrow_left_256.png"))
ImageList_ReplaceIcon(hImageList, -1, AfxGdipIconFromRes(hInst, "IDI_ARROW_LEFT_48"))


we can use


AfxGdipAddIconFromFile(hImageList, ExePath & "\arrow_left_256.png")
AfxGdipAddIconFromRes(hImageList, hInst, "IDI_ARROW_LEFT_48")


and don't worry about destroying the temporary icon.

Paul Squires

Quote from: Jose Roca on May 29, 2016, 04:56:42 PM
See http://www.planetsquires.com/protect/forum/index.php?topic=3838.new#new

With the new functions, instead of


ImageList_ReplaceIcon(hImageList, -1, AfxGdipIconFromFile(ExePath & "\arrow_left_256.png"))
ImageList_ReplaceIcon(hImageList, -1, AfxGdipIconFromRes(hInst, "IDI_ARROW_LEFT_48"))


we can use


AfxGdipAddIconFromFile(hImageList, ExePath & "\arrow_left_256.png")
AfxGdipAddIconFromRes(hImageList, hInst, "IDI_ARROW_LEFT_48")


and don't worry about destroying the temporary icon.


This was a very nice addition. I changed my code to use this new code and now it looks much more compact and visually appealing as well as now knowing that I don't have to worry about destroying the temporary icon.
Paul Squires
PlanetSquires Software
WinFBE Editor and Visual Designer

José Roca

#29
We can't think of all the problems in advance, but we have enough knowledge of the Windows API to solve them when they appear. Writing a complex application brings them to light. I did write CSED during the beta testing of PB9 and used purposely many of the new features of the beta compiler. This helped me to find many bugs that could have not discovered with trivial tests.

Working with the new resize class I realized that can't be used to resize the tab pages (modeless windows associated with the tabs), so I have added the following function:
http://www.planetsquires.com/protect/forum/index.php?topic=3838.new#new

Works nicely with tab pages created with the CTabPage class.