Thank you for this advice. Actually I mean changing color for a particular label. I understand an idea about drawing a menu is give in topic (Function dlg_menu_draw) :
Really much work. Need to store item text/id/color in array, get menu DC, calculate text width, detect is themed or not, get theme handle, calculate text rectangle, draw background, draw text, draw all differently when themed or not, use different colors for normal/selected/disabled state, draw separators differently, process WM_MENUCHAR (menu item selection with keys).
#sub MeasureMenuItem function hDlg MEASUREITEMSTRUCT&m
BSTR b="Menu item text";;this should be retrieved from array that you create before showing menu SIZE z GetTextExtentPoint32W(sub.GetMenuDC b b.len&z)
m.itemWidth=z.cx
m.itemWidth+24;;add space for icon or checkbox if(m.itemHeight<18) m.itemHeight=18;;icon height + 2 pixels between icons
#sub DrawMenuItem function hDlg DRAWITEMSTRUCT&d
int hdc=d.hDC RECT r=d.rcItem int selected(d.itemState&ODS_SELECTED) disabled(d.itemState&ODS_DISABLED)
;this code gets default text color. Change it if need other color. int col=-1 if(disabled) col=GetSysColor(COLOR_GRAYTEXT) elseif(selected) col=GetSysColor(COLOR_HIGHLIGHTTEXT) else col=GetSysColor(COLOR_MENUTEXT)
SetTextColor(hdc col) SetBkMode(hdc TRANSPARENT)
BSTR b="Menu item text";;this should be retrieved from array that you create before showing menu
r.left+24;;add space for icon or checkbox, which you can draw here or use SetThreadMenuIcons
r.top+1
DrawTextW(hdc b b.len&r DT_END_ELLIPSIS)
#sub GetMenuDC function#
;Returns DC to measure menu item text width.
POINT-- m ;;x=DC, y=oldFont if m.x=0 ,NONCLIENTMETRICSW nc.cbSize=sizeof(nc) ,SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, nc.cbSize,&nc,0); ,int font=CreateFontIndirectW(&nc.lfMenuFont) ,m.x=CreateCompatibleDC(0) ,m.y=SelectObject(m.x font) ,atendsub.__DeleteMenuDC&m ret m.x
I used SetThreadMenuIcons to add icons to labels. I experienced overlapping (over-striking). Then I left-padded label stings with a few spaces. It worked. However, I am not sure this is the proper way to do it.
Let me ask one additional question. I understand that using QM Menu Editor you may produce either menu bars (run with ShowDialog) or popupmenus (run with ShowMenu). Is it possible to run the present item as popup menu?
Dear Gintaras, Have a nice day!
I am sorry if bothering, however I cannot avoid two more questions :
1. When I click on 3, then menu appears and variable "i" gets the proper value for this menu item. Nevertheless, the relevant menu value (for example 100) does not work, probably because "i" does not convey its value to wParam. Let me add that if this same menu item is invoked through menu label "File" it is working properly.
Your advice is mostly welcome.
2. If I wanted to invoke menu sub.GetMenuDef directly, without showing the main dialogue, then I thought to include in WM_INITDIALOG
Thank you, but I am afraid your advice is not very clear to me. What I actually do is getting the return value as shown in the above example. Could you please elaborate your advice, upon your availability.
str si.getmacro(getopt(itemid)1) str caller.getmacro(getopt(itemid 1)1);err caller=si if ideb;min0;errout"<>%s : <open ''%s /%i''>%s</open> - Called by : %s"NowT si _error.place si caller
str si.getmacro(getopt(itemid)1) str caller.getmacro(getopt(itemid 1)1);err caller=si if ideb;min0;errout"<>%s : <open ''%s /%i''>%s</open> - Called by : %s"NowT si _error.place si caller
#sub MeasureMenuItem function hDlg MEASUREITEMSTRUCT&m
m.itemWidth=200;;there are several API functions to get string width, for example GetTextExtentPoint32W
m.itemWidth+24;;add space for icon or checkbox ;if(m.itemHeight<18) m.itemHeight=18 ;;icon height + 2 pixels between icons if(m.itemHeight<24) m.itemHeight=24;;icon height + 2 pixels between icons
#sub DrawMenuItem function hDlg DRAWITEMSTRUCT&d
str si.getmacro(getopt(itemid)1) str caller.getmacro(getopt(itemid 1)1);err caller=si if ideb;min0;errout"<>%s : <open ''%s /%i''>%s</open> - Called by : %s"NowT si _error.place si caller
IStringMap- label
int hdc=d.hDC RECT r=d.rcItem int selected(d.itemState&ODS_SELECTED) disabled(d.itemState&ODS_DISABLED)
;this code gets default text color. Change it if need other color. int col=-1 int color
if d.itemID=103; color=475617 if d.itemID=105; color=108031 if(disabled) ;,col=GetSysColor(COLOR_GRAYTEXT) ;,https://msdn.microsoft.com/en-us/library/windows/desktop/ms724371(v=vs.85).aspx ,col=GetSysColor(COLOR_HOTLIGHT) else ,if(selected) ,,col=GetSysColor(COLOR_HIGHLIGHTTEXT) ,else ,,col=iif(color color GetSysColor(COLOR_MENUTEXT))
SetTextColor(hdc col) SetBkMode(hdc TRANSPARENT)
BSTR b lpstr v=label.Get(F"{d.itemID}") if(v) ,b=v else ,_s=F"Value not found for key {d.itemID} - Caller : <open>{caller}</open> " ,min0;errout"<>%s : <open ''%s /%i''>%s</open> - %s"NowT si _error.place si _s ,mac"Warning_QM" si 0 ,end
;BSTR b="Menu item text" ;;this should be retrieved from array that you create before showing menu
r.left+24;;add space for icon or checkbox, which you can draw here or use SetThreadMenuIcons
r.top+1
When calculating the string width, I get slighter higher values in MeasureMenuItem than in DrawMenuItem> I would appreciate it if you could kindly comment on it. I use the following statements in these sub-functions :
To create common menu DC I use this algorithm. Maybe a better way exist.
Get NONCLIENTMETRICSW with SystemParametersInfoW(SPI_GETNONCLIENTMETRICS...);
From its lfMenuFont create font with CreateFontIndirectW.
Create DC with CreateCompatibleDC and select the font with SelectObject.
Thank you for your interest regarding this thread. Your questions are dealt with as it follows:
1. ideb is a global variable initialised in init2 for debugging purposes. Usually, its value is zero.
2. NowT is a simple time output routine. It may be modified according to the user's preferences. I have included it in an updated version of SmartMenu.qml above.
3. Warning_QM is a routine which outputs audio/screen messages in the case of error. It may be modified according to the user's preferences. I have included it in an updated version of SmartMenu.qml above.
4. GVarOut and LVarOut are routines called in a sample menu routine I included for demo purposes. They have nothing to do with this thread. They have to be replaced by the end user, which writes his own menu routine.
Please do not hesitate to ask any further questions. Let me add that I am writing computer software since 1968, under almost all operating systems, mainly for data acquisition and processing. I must admit that Quick Macros is the best platform, from every point of view, to my opinion. Congratulations are due to Gintaras for this perfect product, further to those for the present thread.
Thank you for your interest. It is probably a bug. I will investigate it thoroughly and I will let you know accordingly. I am sorry for this inconvenience.
The bug is due to the column ( after d:\ico\... etc. It is my bug. Actually, I always use symbolic links for icons, and I missed this case. I will correct it as soon as possible and I will upload a new version. Many thanks for your comment.
Thank you very much. It works fine now.
I have other questions:
- What make up the color number at the end when you want to add color to an item?
- Besides coloring each item with different color, could you make an item bold or italic too?
1. You can help on QM colors by using lemma "color" in QM.
Colors in QM are defined as BGR
0x000000 - black
0xFFFFFF - white
0x0000FF - red
0x00FF00 - green
0xFF0000 - blue
0x00FFFF - yellow (red+green)
0xC0C0C0 - gray
0x808080 - dark gray
0x008000 - dark green
You may get int values for other colors using any relevant layered product, for example "colopicker"
2. I am working on changing font characteristics (bold & italic). I will report any outcome.
str si.getmacro(getopt(itemid)1) if ideb;out"%s : %s"NowT si int col str s
;g1 if(ColorDialog(col s)) ,;out "0x%06X" col ,;out s ,s.format("0x%06X" col) ,_s="Selected color string in Clipboard - Colors in QM are defined as BGR" , ,Task_Message _s 0 col 1 ,_s.from("Selected BGR-QM color code :[][]" s "[][]Continue ?") ,int i=mes(_s si "YN") ,s.setclip ,beeS300300 else ,ret if i=89;goto g1
I have found the following version somewhere in the forum, I am afraid I do not remember where :
;Shows Color dialog. ;Returns 1 on OK, 0 on Cancel.
;colorInt - receives color value in format 0xBBGGRR. ;colorStr - receives color formatted as string. ;hwndOwner (QM 2.3.4) - handle of owner window or 0.
;EXAMPLE ;int col ;if(ColorDialog(col)) ,;out "0x%X" col
type___MYCOLORS ft c[16] ___MYCOLORS+ ___mycolors if(___mycolors.ft=0) ___mycolors.ft=1;for(_i 016) ___mycolors.c[_i]=0xa0a0a0