 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Sun Jan 22, 2006 12:26 am Post subject: assign bitmap to any item in any AHk menu |
|
|
Work with context menu:
| Code: |
Menu, menuEmpty, Add
Menu, menuContext$Level2, Add, :menuEmpty
Menu_AssignBitmap( "menuContext$Level2", 1, "coffee.bmp", true )
Menu, menuContext$Level2, Add, empty, :menuEmpty
Menu, menuContext$Level2, Add, world, :menuEmpty
Menu_AssignBitmap( "menuContext$Level2", 3, "coffee.bmp", true )
Menu, menuContext, Add, empty 1, :menuEmpty
Menu, menuContext, Add, empty 2, :menuEmpty
Menu, menuContext, Check, empty 2
Menu_AssignBitmap( "menuContext", 2, "coffee.bmp", true, "coffee.bmp", false )
Menu, menuContext, Add, :menuContext$Level2
Gui, Show, x50 y50 w400 h200
return
GuiContextMenu:
Menu, menuContext, Show
return
|
Work with Tray menu:
| Code: |
Menu, menuEmpty, Add
Menu, Tray, NoStandard
Menu, Tray, Add, Hello, :menuEmpty
Menu_AssignBitmap( "Tray", 1, "coffee.bmp", true )
Menu, Tray, Add
Menu, Tray, Standard
|
Work with Window menu bar:
| Code: |
Menu, menuEmpty, Add
Menu, menuFile, Add, Hello, :menuEmpty
Menu_AssignBitmap( "menuFile", 1, "coffee.bmp", false )
Menu, menuMain, Add, File, :menuFile
Gui, Menu, menuMain
Gui, Show, x50 y50 w400 h200
|
| Code: |
/* p_menu = "MenuName" (e.g., Tray, etc.)
p_item = 1, ...
p_bm_unchecked,
p_bm_checked = path to bitmap/false
p_unchecked_face,
p_checked_face = true/false (i.e., true = pixels with same color as first pixel are transparent)
*/
Menu_AssignBitmap( p_menu, p_item, p_bm_unchecked, p_unchecked_face=false, p_bm_checked=false, p_checked_face=false )
{
static h_menuDummy
if h_menuDummy=
{
Menu, menuDummy, Add
Menu, menuDummy, DeleteAll
Gui, 99:Menu, menuDummy
Gui, 99:Show, Hide, guiDummy
old_DetectHiddenWindows := A_DetectHiddenWindows
DetectHiddenWindows, on
Process, Exist
h_menuDummy := DllCall( "GetMenu", "uint", WinExist( "guiDummy ahk_class AutoHotkeyGUI ahk_pid " ErrorLevel ) )
if ReportError( ErrorLevel or h_menuDummy = 0, "Menu_AssignBitmap: GetMenu", "h_menuDummy = " h_menuDummy )
return, false
DetectHiddenWindows, %old_DetectHiddenWindows%
Gui, 99:Menu
Gui, 99:Destroy
}
Menu, menuDummy, Add, :%p_menu%
h_menu := DllCall( "GetSubMenu", "uint", h_menuDummy, "int", 0 )
if ReportError( ErrorLevel or h_menu = 0, "Menu_AssignBitmap: GetSubMenu", "h_menu = " h_menu )
return, false
success := DllCall( "RemoveMenu", "uint", h_menuDummy, "uint", 0, "uint", 0x400 )
if ReportError( ErrorLevel or ! success, "Menu_AssignBitmap: RemoveMenu", "success = " success )
return, false
Menu, menuDummy, Delete, :%p_menu%
if ( p_bm_unchecked )
{
hbm_unchecked := DllCall( "LoadImage"
, "uint", 0
, "str", p_bm_unchecked
, "uint", 0 ; IMAGE_BITMAP
, "int", 0
, "int", 0
, "uint", 0x10|( 0x20*p_unchecked_face ) ) ; LR_LOADFROMFILE|LR_LOADTRANSPARENT
if ReportError( ErrorLevel or ! hbm_unchecked, "Menu_AssignBitmap: LoadImage: unchecked", "hbm_unchecked = " hbm_unchecked )
return, false
}
if ( p_bm_checked )
{
hbm_checked := DllCall( "LoadImage"
, "uint", 0
, "str", p_bm_checked
, "uint", 0
, "int", 0
, "int", 0
, "uint", 0x10|( 0x20*p_checked_face ) )
if ReportError( ErrorLevel or ! hbm_checked, "Menu_AssignBitmap: LoadImage: checked", "hbm_checked = " hbm_checked )
return, false
}
success := DllCall( "SetMenuItemBitmaps"
, "uint", h_menu
, "uint", p_item-1
, "uint", 0x400 ; MF_BYPOSITION
, "uint", hbm_unchecked
, "uint", hbm_checked )
if ReportError( ErrorLevel or ! success, "Menu_AssignBitmap: SetMenuItemBitmaps", "success = " success )
return, false
return, true
}
ReportError( p_condition, p_title, p_extra )
{
if p_condition
MsgBox,
( LTrim
[Error] %p_title%
EL = %ErrorLevel%, LE = %A_LastError%
%p_extra%
)
return, p_condition
}
|
Last edited by shimanov on Thu Mar 23, 2006 5:21 am; edited 5 times in total |
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 5009 Location: imaginationland
|
Posted: Sun Jan 22, 2006 12:50 am Post subject: |
|
|
Thats great! We don't have to wait for in-built support now
I found one issue, bitmaps with magenta backgrounds are shown to have the magenta colour. It's supposed to be negated and treated as a transparent secion right? |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Sun Jan 22, 2006 1:37 am Post subject: |
|
|
| Titan wrote: | | Thats great! |
Thanks. It was a fun challenge to resolve.
| Quote: | | one issue, bitmaps with magenta backgrounds are shown to have the magenta colour. It's supposed to be negated and treated as a transparent secion right? |
Why?
Do you have the following in mind:
| MSDN:LoadImage wrote: |
LR_LOADTRANSPARENT [=0x20]
Retrieves the color value of the first pixel in the image and replaces the corresponding entry in the color table with the default window color (COLOR_WINDOW). All pixels in the image that use that entry become the default window color. This value applies only to images that have corresponding color tables.
Do not use this option if you are loading a bitmap with a color depth greater than 8bpp.
If fuLoad includes both the LR_LOADTRANSPARENT and LR_LOADMAP3DCOLORS values, LRLOADTRANSPARENT takes precedence. However, the color table entry is replaced with COLOR_3DFACE rather than COLOR_WINDOW.
|
|
|
| Back to top |
|
 |
Titan
Joined: 11 Aug 2004 Posts: 5009 Location: imaginationland
|
Posted: Sun Jan 22, 2006 2:56 pm Post subject: |
|
|
| That's the one. I'm not sure how I'd impliment it though. |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Sun Jan 22, 2006 8:31 pm Post subject: |
|
|
Titan:
Change each of the lines:
, "uint", 0x10 ) ; LR_LOADFROMFILE
to
, "uint", 0x10|0x20 ) ; LR_LOADFROMFILE|LR_LOADTRANSPARENT |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 5574
|
Posted: Sun Jan 22, 2006 8:59 pm Post subject: |
|
|
"Splendid Job" Shimanov
Menu_AssignBitmap() function is terrific, I tried it with my script`s tray menu and it looks so lively now!
Thanks for posting it. _________________ SKAN - Suresh Kumar A N |
|
| Back to top |
|
 |
AGU Guest
|
Posted: Sun Jan 22, 2006 10:10 pm Post subject: |
|
|
Hello shimanov,
thx for your script/function. Works great. I commented the script as far as I understood it and made some slight formating changes. I'm really trying to understand what the script is doing.
Attention: Further text below scriptcode
| Code: | Menu_AssignBitmap(p_menu, p_path, p_bm_unchecked=false, p_bm_checked=false)
{
; Thanks to shimanov for this function
; Details under http://www.autohotkey.com/forum/viewtopic.php?p=44577
; p_menu : menu name
; p_path : number of menu entry (1st entry = "1", 2nd entry = "2", ... )
; p_bm_unchecked : path to .bmp for unchecked menu entry
; p_bm_checked : path to .bmp for checked menu entry
static menu_count, menu_list, h_menuDummy
If h_menuDummy=
{
menu_count = 0
menu_list = |
; Save current 'DetectHiddenWindows' mode to reset it later
Old_DetectHiddenWindows := A_DetectHiddenWindows
DetectHiddenWindows, on
; Retrieve scripts PID
Process, Exist
pid_this := ErrorLevel
; Create menuDummy and assign to Gui99
Menu, menuDummy, Add
Menu, menuDummy, DeleteAll
Gui, 99:Menu, menuDummy
; Retrieve menu handle
h_menuDummy := DllCall( "GetMenu", "uint", WinExist( "ahk_class AutoHotkeyGUI ahk_pid " pid_this ) )
; Remove menu bar 'menuDummy'
Gui, 99:Menu
; Reset 'DetectHiddenWindows' mode to old setting
DetectHiddenWindows, %Old_DetectHiddenWindows%
}
If ( ! InStr( menu_list, "|" p_menu ",", false ) )
{
menu_count++
menu_list = %menu_list%%p_menu%,%menu_count%|
Menu, menuDummy, Add, :%p_menu%
}
root := InStr( menu_list, ",", false, InStr( menu_list, "|" p_menu ",", false ) ) + 1
StringMid, root, menu_list, root, InStr( menu_list, "|", false, root ) - root
p_path = %root%|%p_path%
StringSplit, path, p_path, |
; Assign above retrieved menu handle to 'h_menu'
h_menu := h_menuDummy
loop, % path0 - 1
h_menu := DllCall("GetSubMenu", "uint", h_menu, "int", path%A_Index% - 1)
; Load bitmap for unchecked menu entries
If (p_bm_unchecked)
{
hbm_unchecked := DllCall( "LoadImage"
, "uint", 0
, "str", p_bm_unchecked
, "uint", 0 ; IMAGE_BITMAP
, "int", 0
, "int", 0
, "uint", 0x10 ) ; LR_LOADFROMFILE
If (ErrorLevel or ! hbm_unchecked)
{
MsgBox, [Menu_AssignBitmap: LoadImage: unchecked] failed: EL = %ErrorLevel%
Return, false
}
}
; Load bitmap for checked menu entries
If (p_bm_checked)
{
hbm_checked := DllCall( "LoadImage"
, "uint", 0
, "str", p_bm_checked
, "uint", 0 ; IMAGE_BITMAP
, "int", 0
, "int", 0
, "uint", 0x10 ) ; LR_LOADFROMFILE
If (ErrorLevel or ! hbm_checked)
{
MsgBox, [Menu_AssignBitmap: LoadImage: checked] failed: EL = %ErrorLevel%
Return, false
}
}
; On success assign image to menu entry
success := DllCall( "SetMenuItemBitmaps"
, "uint", h_menu
, "uint", path%path0%-1
, "uint", 0x400 ; MF_BYPOSITION
, "uint", hbm_unchecked
, "uint", hbm_checked )
If (ErrorLevel or ! success)
{
MsgBox, [Menu_AssignBitmap: SetMenuItemBitmaps] failed: EL = %ErrorLevel%
Return, false
}
Return, true
}
|
However I've got some problems in understanding this little follwing passage. Just in case you like would you be so kind to write some explaining lines? Just for me that I can make some explaining comments.
| Code: | If ( ! InStr( menu_list, "|" p_menu ",", false ) )
{
menu_count++
menu_list = %menu_list%%p_menu%,%menu_count%|
Menu, menuDummy, Add, :%p_menu%
}
root := InStr( menu_list, ",", false, InStr( menu_list, "|" p_menu ",", false ) ) + 1
StringMid, root, menu_list, root, InStr( menu_list, "|", false, root ) - root
p_path = %root%|%p_path%
StringSplit, path, p_path, |
; Assign above retrieved menu handle to 'h_menu'
h_menu := h_menuDummy
loop, % path0 - 1
h_menu := DllCall("GetSubMenu", "uint", h_menu, "int", path%A_Index% - 1) |
Cheers
AGU |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Mon Jan 23, 2006 1:04 am Post subject: |
|
|
| AGU wrote: | | I commented the script |
Thank you. I really hate adding explicit comments. It's like doing the work twice.
| Code: |
if ( ! InStr( menu_list, "|" p_menu ",", false ) )
{
menu_count++
menu_list = %menu_list%%p_menu%,%menu_count%|
Menu, menuDummy, Add, :%p_menu%
}
root := InStr( menu_list, ",", false, InStr( menu_list, "|" p_menu ",", false ) )+1
StringMid, root, menu_list, root, InStr( menu_list, "|", false, root )-root
p_path = %root%|%p_path%
StringSplit, path, p_path, |
|
"Menu, menuDummy, Add, :%p_menu%" is where the magic happens. It attaches menus to a menu with a known handle (i.e., menuDummy) and enables retrieving its associated handle via "GetSubMenu" -- pretty cool.
The rest of the code manages the menu_list variable, which contains the menu names and their item position in menuDummy.
| Code: |
h_menu := h_menuDummy
loop, % path0-1
h_menu := DllCall( "GetSubMenu", "uint", h_menu, "int", path%A_Index%-1 )
|
Determines menu handle for the requested menu and path on each call. This is necessary, but insufficient, to accommodate a deleted menu/item. |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Mon Jan 23, 2006 3:14 am Post subject: update: 2006.01.22 |
|
|
changes:
* support transparent bitmaps (as suggested by Titan) |
|
| Back to top |
|
 |
AGU Guest
|
Posted: Mon Jan 23, 2006 2:06 pm Post subject: |
|
|
Hello again.
| Quote: | | p_path = relative to p_menu (e.g., 3|1|2 = level 1: item 3|level 2: item 1|level 3: item 2) | Do I understand right, that I can assign more than one bitmap at once?
Concerning the support for transparent bitmaps:
How does that work? I add a bitmap and the first pixel (x1 * y1) becomes the transparent color for the whole bitmap? The transparent color pixels get the same color as the menu background when I understand that right.
I used bitmaps with white background and didn't make use of LR_LOADTRANSPARENT. But the background gets transparent, too. Why? Is that because you should use monochrome bitmaps normally? MSDN said s.th about this and that by using monochrome bitmaps the white background gets transparent.
Another thing:
What's the max-size for these bitmaps. I realized that 16x16 bitmaps get cut when you add them to a context menu. 13x13px is the maxsize I could use for context menus. Is that normal? And why don't they just scale to the correct size instead of getting cut?
Cheers
AGU |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Mon Jan 23, 2006 8:27 pm Post subject: |
|
|
| AGU wrote: | | Do I understand right, that I can assign more than one bitmap at once? |
Two different bitmaps can be assigned to each item, one for unchecked and one for checked.
| Quote: | | Concerning the support for transparent bitmaps |
Refer to my earlier post containing a description of the LR_LOADTRANSPARENT flag.
| Quote: | | What's the max-size for these bitmaps. |
| Code: |
SysGet, w, 71
SysGet, h, 72
MsgBox, %w%, %h%
|
|
|
| Back to top |
|
 |
Guest
|
Posted: Tue Jan 24, 2006 4:56 pm Post subject: |
|
|
| Quote: | | Two different bitmaps can be assigned to each item, one for unchecked and one for checked. | Yeah I know. But I understand the following line in this way, that you assign these two bitmaps to three different items namely:
"level 1: item 3",
"level 2: item 1"
"level 3: item 2"
| Quote: | | p_path = relative to p_menu (e.g., 3|1|2 = level 1: item 3|level 2: item 1|level 3: item 2) |
I understand it in the way that you assign 3 * 2(per item) = 6 pictures at once. My question aims at if I understood that right.
So, did I? Can you, by using "|", assign bitmaps to multiple entries on different menu layers (submenus)?
Cheers
AGU |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Tue Jan 24, 2006 8:08 pm Post subject: |
|
|
| Anonymous wrote: | assign these two bitmaps to three different items namely:
"level 1: item 3",
"level 2: item 1"
"level 3: item 2" |
Now I understand your question. The path allows specification of a single item located on a submenu n-levels removed from a top level menu.
There are two ways to specify an item:
| Code: |
Menu, < level 2 >, Add, item 1, ...
Menu, < level 1 >, Add, item 2, :< level 2 >
; direct
Menu_AssignBitmap( "< level 2 >", "1", ... )
; indirect
Menu_AssignBitmap( "< level 1 >", "2|1", ... )
|
The difference between the two method is purely stylistic.
Now that I think about it, the technique used to determine the handle of submenus, obviates the need for a path specification. I'll have to update the code to reflect this capability. |
|
| Back to top |
|
 |
AGU Guest
|
Posted: Tue Jan 24, 2006 8:31 pm Post subject: |
|
|
Ahhh, thx now i got it.
Some short kind of documentation won't be that bad.
Cheers
AGU
P.S. looking forward to your code update. |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Tue Jan 24, 2006 8:50 pm Post subject: update: 2006.01.24 |
|
|
changes:
* simplified item specification method (removed indirect method)
Thanks to AGU for keeping me on my toes. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|