AutoHotkey Community

It is currently May 27th, 2012, 3:59 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: January 22nd, 2006, 12:26 am 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
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 March 23rd, 2006, 5:21 am, edited 5 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 22nd, 2006, 12:50 am 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5347
Location: UK
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?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 22nd, 2006, 1:37 am 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 22nd, 2006, 2:56 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5347
Location: UK
That's the one. I'm not sure how I'd impliment it though.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 22nd, 2006, 8:31 pm 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
Titan:

Change each of the lines:

    , "uint", 0x10 ) ; LR_LOADFROMFILE

to

    , "uint", 0x10|0x20 ) ; LR_LOADFROMFILE|LR_LOADTRANSPARENT


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 22nd, 2006, 8:59 pm 
Offline
User avatar

Joined: December 26th, 2005, 4:40 pm
Posts: 8776
"Splendid Job" Shimanov :D

Menu_AssignBitmap() function is terrific, I tried it with my script`s tray menu and it looks so lively now!

Thanks for posting it.

_________________
URLGet - Internet Explorer based Downloader
StartEx - Portable Shortcut Link


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 22nd, 2006, 10:10 pm 
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. :mrgreen:
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: January 23rd, 2006, 1:04 am 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: update: 2006.01.22
PostPosted: January 23rd, 2006, 3:14 am 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
changes:
    * support transparent bitmaps (as suggested by Titan)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 23rd, 2006, 2:06 pm 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: January 23rd, 2006, 8:27 pm 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
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%


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 24th, 2006, 4:56 pm 
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


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: January 24th, 2006, 8:08 pm 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: January 24th, 2006, 8:31 pm 
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.


Report this post
Top
  
Reply with quote  
 Post subject: update: 2006.01.24
PostPosted: January 24th, 2006, 8:50 pm 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
changes:
    * simplified item specification method (removed indirect method)


Thanks to AGU for keeping me on my toes.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 25 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group