Drawing icons instead of bitmaps in a MFC CMenu? - mfc

I can use an bitmap in a menu
CMenu men;
CBitmap b;
b.LoadBitmap(IDB_0);
men.AppendMenu( MF_ENABLED,1,&b);
I can draw an icon into a DC
CImageList IL;
IL.Create(70, 14, ILC_COLOR16 | ILC_MASK, 1, 0);
IL.Add(AfxGetApp()->LoadIcon(IDI_0));
IL.Draw ( pDC, 0, rcIcon.TopLeft(), ILD_BLEND50 );
But I cannot find a simple way to show an icon in a menu. I would like to do this
CMenu men;
CBitmap b;
// here the miracle happens, load the icon into the bitmap
men.AppendMenu( MF_ENABLED,1,&b);
Seems like this should be possible.
This is the same question as this. However that question referred to the MFC feature pack, did not get answered, and has shown no activity for a month, so I thought it would be worthwhile to ask it again in reference to basic MFC.

I asked the question you reference.
The way to add (normal, 16-bit color) icons to menus is to make a toolbar with the same resource id as the menu you want to have icons in. You then assign id's to each of the toolbar buttons, the same id's as the menu entries. Make a wizard-generated new MFC application and you'll see how it works there.
The answers to the question I posted suggested that it should work the same for 32-bit images with transparency for the Feature Pack toolbars; I haven't gotten around to test it out though.
If your specific problem is how to make dynamically-generated menus, I think you should pass the id of an existing entry in a toolbar and then that image will be used.
Not a real answer to your question but maybe it'll point you in the right direction.

Good code. Please note that this shows the bitmap image but it is always good to remove the blank space left to the string (used for check/unchek) if you are showing the image.
I did like this.
MENUINFO mi;
mi.cbSize = sizeof(mi);
mi.fMask = MIM_STYLE;
mi.dwStyle = MNS_NOCHECK;
pcSubMenu->SetMenuInfo(&mi);
MENUITEMINFO mii;
mii.cbSize = sizeof mii;
mii.fMask = MIIM_BITMAP;
mii.hbmpItem = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_16_HELP),IMAGE_BITMAP,0,0,LR_SHARED |LR_VGACOLOR |LR_LOADTRANSPARENT);
pcSubMenu->SetMenuItemInfo(ID_CONTENTS,&mii,FALSE);

I think what you are looking for is very similar to what's described here...
www.codeguru.com/cpp/controls/menu/bitmappedmenus/article.php/c165/
mixed with what's described in www.codeproject.com/KB/shell/DynIcon.aspx
Still have to see if it will work.
Tamer

On Windows Vista/Windows7 you can not do that, it's either a 32 BGRA image or the menu is not drawn in the new UI style. There is no workaround, maybe ownerdrawing but i read the style API is not working correctly with menus, so i never tried to get deeper in it.
You should use 32bit BGRA Icons anyway.

In order to set up a bitmap for a menu, you need to call CMenu::SetMenuItemInfo() for each item with something like this:
MENUITEMINFO mii;
mii.cbSize = sizeof mii;
mii.fMask = MIIM_BITMAP;
mii.hbmpItem = bitmapHandle;
menu.SetMenuItemInfo(menuItem,&mii,TRUE);
A further complication with doing this is that this is okay for 256 colour bitmaps, but not full colour 32bit RGBA bitmaps - these will work, but only on Vista, and then only if you present the bitmap as pre-computed RGBA.
In practice, in my code I get round this by using another feature of menu icons, which is to set the hbmpItem to HBMMENU_CALLBACK, which allows a callback to draw the bitmap: I do that for Windows XP and before. The code gets a bit too complicated to post here. As an example, you could have a look at my code at
http://www.ifarchive.org/if-archive/infocom/interpreters/frotz/WindowsFrotzSrc.zip
Look in "MenuBar.h" and "MenuBar.cpp", particularly the code around MenuBar::SetBitmaps().

Related

MFC picture control changes size when DPI awareness disabled or running on Win7

I made an MFC app for my friend using VS2015 in Win10. It looks like this, which is exactly the same as in resource editor.
.
But when he ran the app on his computer in Win7, the Bitmap image in Picture Control enlarges and covers up some text boxes below, which looks like this.
.
After I searched and realized it may be related with DPI awareness. I disabled DPI-Awareness in property page of Manifest Tool and rebuilt. The same thing happened even when it runs in Win10.
Could someone help me explain the cause of this and find a solution to fix the size of the image control? Thanks.
The main problem is that a dialog from a resource is always measured in DLUs.
And DLUs are calculated from the size of the font, that is used for the dialog.
See this article how dialog base units are calculated.
Now you have a static picture control that is sized in DLUs. The bitmap is just scaled in pixels and is never resized, when you assign it to a static dialog control. And because the real size of the static control depends on the used font, you get different layouts for your dialog and your bitmap.
And because just the font changes when you choose no DPI awareness and because the font changes from windows version to windows version your dialog always look different.
Advice: Paint you picture your own and stretch it accordingly.
Also this stackoverflow question is nice documents and shows the effect of DLUs.
And here some code for auto sizeing picture controls.
An auto-sizing bitmap picture control
A simple image preview class using GDI+
CxImage
Normally, I prefer to keep control in my hand by using SetWindowPos() to set the size of image I want in different situations. You can use below two lines to control/set position and size of your image.
Assume ID of the Picture Control is IDC_STATIC2 then you can use like:
CStatic * pStatic = (CStatic *) GetDlgItem(IDC_STATIC2);
pStatic->SetWindowPos(NULL,20,20,50,50,0);

How to Make HICON grayed? [duplicate]

I'm finally getting around to adding icons to our pull down menus:
In this image, you can see that everything but the highlighted line is okay. The highlighted line is fine except for the icon, which is drawn in color, instead of grayed.
I'm basing my code off of a minimalist approach:
http://www.codeproject.com/Articles/16529/Simple-Menus-That-Display-Icons-Minimalistic-Appro?msg=4166441#xx4166441xx
Basically, this only requires that I draw the icon, and I don't have to manage all aspects of a menu item using custom code. Pretty nifty.
It works for our purposes except when selecting a disabled (grayed) menu item.
But when the menu item is grayed and selected, then the drawn icon appears as it would if it were enabled. Wrong. :(
Yet the exact same drawing code works when the background is highlighted/selected.
That leads me to believe that there is some stated contained entirely in the HDC that must control how the icon is appearing - since the following code works under all conditions but selected:
::DrawIconEx(lpdis->hDC, lpdis->rcItem.left+0, lpdis->rcItem.top, pIcon->GetHandle(), pIcon->GetSize().cx, pIcon->GetSize().cy, 0, NULL, DI_NORMAL);
Does anyone know what state is encapsulated in the HDC that would control how DrawIconEx functions? If I can replicate the HDC state during selected drawing as found when not-selected-drawing, I should be able to generate the grayed icons without resorting the 30-50 line implementations that manually gray-scale the icon in memory.
You can use:
DrawState(...)
API function, with DSS_DISABLED flag, but I am not sure about the quality of the output.

Drawing to the desktop via injection

I'd like to draw to the desktop wallpaper area with directX 9 in particular. Under the icons and text above the wallpaper.
Similar to Okozo or one of VLC's modes, or Dreamscene.
So there's a lot of similar questions to this but no working examples or tutorials.This A simmilar question but different approach seems pretty useful. A few years ago I was searching and found this site and code.
It's perfect aside from one big issue the icon text gets blocky even with alpha blending. I tried a few fixes but I wasn't able to find any helpful documentation maybe I just wasn't using the right words for searching, maybe it's proprietary. I think I fixed that with a call to invalidate the desktop area but I can't really tell as in the process I messed up the alpha values for the text so it doesn't properly draw the font color. So how do I alter the text for proper alpha blending?
Pouet's links are all dead
I know I should post a snippet but I can't pin down where the problem is as it's more an unexpected feature.
I've been searching for this code for too long.
I'd like to write a Dreamscene like app witch can render dynamic contents other than just video files, and this one may be the most hopful solution.
I compiled your code in VS2010 Win7x64 and found:
Desktop icon text become transparent just like Dreamscene do when the window is like:
0x00150138 "Program Manager" Progman
0x000605D6 "" SHELLDLL_DefView
0x000C05BA "FolderView" SysListView32
Desktop icon text become normal but not clear enough when the window is like:
0x000B007C "" WorkerW
0x000605D6 "" SHELLDLL_DefView
0x000C05BA "FolderView" SysListView32
0x000C05BA "FolderView" SysListView32
0x000511E2 "" WorkerW
0x00150138 "Program Manager" Progman
I tried this method Draw Behind Desktop Icons in Windows 8 to make the window status always be like the second condition; and tried to draw on WorkerW window above Progman window with D3D, but got nothing rendered out.
So far there's nothing helpful, dumping the bitmap used by memoryDC may help, which I'll try latter.
If you got any further approach, please let me know.
It has been long time since I last use English, Sorry for my mistake if any.
Update:Clear Icon Text got!
add this under d3ddev->BeginScene();
d3ddev->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
d3ddev->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_GAUSSIANQUAD);
and this:
HWND desktop = GetDesktopWindow();
HWND explorer = FindWindowEx(desktop, 0, _T("Progman"), _T("Program Manager"));
SendMessageTimeout(explorer, 0x052C, 0, 0, SMTO_NORMAL, 3000, NULL);
HWND defView = 0;
HWND worker = 0;
while(!defView) {
worker = FindWindowEx(desktop, worker, _T("WorkerW"), 0);
if(worker) {
defView = FindWindowEx(worker, 0, _T("SHELLDLL_DefView"), 0);
}
else break;
}
if (!worker){ /*DBG("First WorkerW failed");*/ return 0;}
worker = FindWindowEx(desktop, (HWND)worker, _T("WorkerW"), 0); //find the next WorkerW
if (!worker){ /*DBG("Created WorkerW not found");*/ return 0;}
Still drawing on the listView, but worker window must exist. This code runs with Aero Theme enabled only.

Adding a transparent bitmap to a windows button

It's a while since I've done this, but I'm trying to add a custom button graphic to a windows button, with some transparent areas. I've tried various schemes but can't seem to get the transparent areas to show. Here's my code:
hbmpUpDisabled = LoadImage(instance,MAKEINTRESOURCE(IDB_UPARROWDISABLED), IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
SendMessage(GetDlgItem(hWndDlg, IDC_MOVEUP),BM_SETIMAGE,(WPARAM)IMAGE_BITMAP,(LPARAM)hbmpUpDisabled);
Does anyone notice any problems here? It works if my bitmap is a 1-bit bitmap. I couldn't get a 32 bit bitmap to work, and I'm not sure how to setup a 24 bit or 8 bit bitmap to do it.... I tried a custom 255,0,255 color (which IIRC is a default transparent value), but so far no joy....
LR_LOADMAP3DCOLORS should map grey - in the source image - to to the current button face color. Buttons do not use AlphaBlt or TransparentBlt so there is no way to actually (short of custom painting) set a bitmap with transparent or alpha'd areas onto a button and expect it to work. You just have to pre-prepare the bitmap with the correct button color in its background areas.
That said - I suspect that some of these restrictions may be lifted for buttons implemented by common controls v6. Add commctl 6 as a dependend assembly to your exe and see if the behaviour changes.

Why are not all texts of my MFC applicatiopn displayed using ClearType?

I've got an MFC application that is built with VC6. When ClearType is enabled (Windows XP) some texts are rendered smoothly, i.e. with ClearType, and others are not.
Dialog texts don't seem to ever get rendered with ClearType. Some list controls, however, have it enabled completely, others only in their headers.
What could be the reason for this? Where should I look to find out why it works only in some places and doesn't in others?
Update
As requested, here is an enlarged screenshot. Obfuscated but the important parts should be visible.
In List 1 only the heading is smooth, the content is not.
In List 2 both, heading and list items are smooth.
The Dialog at the bottom is not using ClearType either.
Bitmap fonts will never use ClearType. Usually you won't use a bitmap font, but I believe the default selected into a DC is the System font, which is bitmap.
ClearType is a quality property for fonts. You should get the LOGFONT for your CFont and set the lfQuality property. Here's an example.
CFont *pFont = CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT));
LOGFONT logFont;
pFont->GetLogFont(&logFont);
logFont.lfQuality = CLEARTYPE_NATURAL_QUALITY;
CFont font2;
font2.CreateFontIndirect(&logFont);
Note: you can use either CLEARTYPE_QUALITY or CLEARTYPE_NATURAL_QUALITY, test both to see which looks best.