AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[module] Toolbar Control 1.0 b1
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Fri Jan 11, 2008 12:52 pm    Post subject: Reply with quote

TB_SETBUTTONSIZE works
I mistekenly used TB_SETBITMAPSIZE prviously Rolling Eyes

Thx Very Happy
_________________
Back to top
View user's profile Send private message MSN Messenger
Lexikos



Joined: 17 Oct 2006
Posts: 2602
Location: Australia, Qld

PostPosted: Fri Jan 11, 2008 1:55 pm    Post subject: Reply with quote

I added four buttons with image only, then gave three text.

TB_SETBUTTONSIZE leaves the images centered, so the buttons must be higher to compensate:


TB_SETBUTTONWIDTH updates the button height to fit text (TB_SETBUTTONSIZE not necessary):
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Fri Jan 11, 2008 2:29 pm    Post subject: Reply with quote

Great discovery Exclamation

This message is good as I don't need to know anything, I can just put some arbitrary values like:

Code:
Toolbar_SetButtonWidth(hToolbar, 10, 1000)


and it works.

Thx dude Very Happy
_________________
Back to top
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Fri Jan 11, 2008 2:58 pm    Post subject: Reply with quote

Quote:
Its a bit slow, though, even with this small sample menu you created but it shows that it was about SetWinDelay as you resize the main window after every insertion..

Its definite that your method suffers cuz of window reposition. When you remove it its fast (its slow regardless SetWinDelay) but window is not vertical.

Vertical toolbar can be also created by using ReBar and some toolbar styles, it will be lot faster, especialy with larger menus.

I will not continue your project as it will be possible with combination of Rebar and Toolbar module once I finish them. I will probably reinvent it then, with just couple lines of code that includes Toolbar.ahk and Rebar.ahk

Another method to speed up your code would be to reposition window in Show function. Then it would work as fast as possible. Thinking about it, its probably better idea then using Rebar for it:

Code:
TbMenu_Show(tbm)
{
    SendMessage, 0x418, 0, 0    ,, ahk_id %tbm% ; TB_BUTTONCOUNT
    bc := ErrorLevel
    VarSetCapacity(rc,16,0)
    SendMessage, 0x427, bc, &rc ,, ahk_id %tbm% ; TB_SETROWS
    w := NumGet(rc,8)-NumGet(rc,0)
    h := NumGet(rc,12)-NumGet(rc,4)
    WinMove, ahk_id %tbm%,, , , w+2, h+2


    WinShow, ahk_id %tbm%
}


I just moved code prior to WinShow from Add function. Much faster.

BTW, I don't know why all icons become grayed when gui looses focus
BTW2, I tried with lot of icons (>20) and it works good and fast after this change. I will definitely reinvent this Smile Toolbar is very flexibile when button position its text, and icon are in question (you can even influence how DrawText works) so menu will be very customizable.
_________________
Back to top
View user's profile Send private message MSN Messenger
Lexikos



Joined: 17 Oct 2006
Posts: 2602
Location: Australia, Qld

PostPosted: Fri Jan 11, 2008 4:51 pm    Post subject: Reply with quote

majkinetor wrote:
(its slow regardless SetWinDelay)
With SetWinDelay,-1 it takes ~5ms per item on my system. That's at least 20x faster than with the default delay. After making the change you suggested, it drops to ~4ms per item...
someone... wrote:
speed gain wouldn't be significant
Rolling Eyes
Quote:
BTW, I don't know why all icons become grayed when gui looses focus
Nor do I. Maybe it could be prevented with WM_CHANGEUISTATE or similar message.
Quote:
I just moved code prior to WinShow from Add function. Much faster.
For that to work as you've posted it, you must've had DetectHiddenWindows On already...

Btw, TbMenu never got to a stage where I considered optimising it...
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Fri Jan 11, 2008 5:22 pm    Post subject: Reply with quote

Quote:
With SetWinDelay,-1 it takes ~5ms per item on my system.
Thats not the case here. I don't know what kind of machine you have but on double core its really slow without changes. Only after change it appears instantious.

Quote:
Rolling Eyes

Rolling Eyes


Quote:
Nor do I. Maybe it could be prevented with WM_CHANGEUISTATE or similar message.

not really some solution....

Quote:
For that to work as you've posted it, you must've had DetectHiddenWindows On already...

lets skip trivial details

Quote:
Btw, TbMenu never got to a stage where I considered optimising it...

Thats obvious. You also said its proof of the concept. I am just sharing my thoughts with you. If that is trouble, I can stop any time...
_________________
Back to top
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Fri Jan 11, 2008 8:05 pm    Post subject: Reply with quote

This is interesting

The Old New Thing wrote:
Why are there both TBSTYLE_EX_VERTICAL and CCS_VERT?

There are two ways to make a vertical toolbar. You can use the common CCS_VERT style, or you can use the TBSTYLE_EX_VERTICAL extended style which is specific to the toolbar. Why are there two ways of doing the same thing?

Because we messed up.

Whoever created the TBSTYLE_EX_VERTICAL extended style didn't realize that there was already a perfectly good way of specifying a vertical toolbar (namely, CCS_VERT).

What's worse, some vertical behavior is controlled by CCS_VERT and some by TBSTYLE_EX_VERTICAL. So if you want a vertical toolbar, you probably want to set both styles to cover all your bases on Windows XP.

Unfortunately, the story doesn't get any better. Once this mistake was discovered, work was done to try to get the two styles in sync, so that setting one automatically set the other. The idea was to ensure that everybody got consistent behavior instead of getting half-and-half if you, say, turned on CCS_VERT and forgot to turn on TBSTYLE_EX_VERTICAL. But this was itself a failure, because there were some programs that let the two styles fall out of sync on purpose because they liked the half-and-half behavior.

It's a mess. We're sorry.
Pre-emptive snarky comment: "This is why Windows sucks."

_________________
Back to top
View user's profile Send private message MSN Messenger
Lexikos



Joined: 17 Oct 2006
Posts: 2602
Location: Australia, Qld

PostPosted: Sat Jan 12, 2008 1:45 am    Post subject: Reply with quote

majkinetor wrote:
Quote:
With SetWinDelay,-1 it takes ~5ms per item on my system.
Thats not the case here. I don't know what kind of machine you have but on double core its really slow without changes.
Athlon XP, single core 2.2 GHz. Laughing 0.2s for 40 items with SetWinDelay,-1.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Sat Jan 12, 2008 8:15 pm    Post subject: Reply with quote

I implemented new version with many updates, basically it supports entire Toolbar API with few final things that I will add later.

Everything works nice except one thing, and I am unable to fix it, no matter what I trie. Its about new feature, customization.

There is new creation flag - ADJUSTABLE - that let the user customize dialog by double clicking toolbar background. It also enables drag and drop of buttons when SHIFT is hold down. This requires user to specify 2 lists - current buttons and available buttons.

Button information is specified as text, each button definition on new line:
Syntax is:

text| icon | state | style
  • text - button text, specify - and skip all other parameters to add separator
  • icon - 1 based icon number in the image list. Set to 0 to add blank icon. Leave blank to use button position as number (not including separators)
  • state - enabled (default), hidden, checked, clicked
  • style - dropdown, check, , checkgroup, autosize (a), noprefix. Successive buttons that have checkgroup flag will act as radio buttons. DropDown makes button menus. Autosize makes this button take care of its size (default in LIST toolbar style)


You add 1 or bunch of buttons using AddButtons function. To add all available buttons, just set button definition in global variable ALL for now (buttons that will be availalbe in customization dialog on the left side)

There are number of selfexplantory functions that you can use. To switch text on or off, use SetMaxTextRows(hToolbar on ? 1: 0)

Before adding buttons you must create toolbar using Add function and set its image list using SetImageList. You can still use system catalogs (by default "1L")

I didn't succeded with integrated Tooltips as even with TOOLTIPS flag (Add function) I don't recieve adequate notifications. However its possilbe to achive that functionality by using HOTITEMCHANGE notification wich fires when user is hovering specific button.

This is the picture of the bug that I can't manage to fix. Perhaps I don't see something, so I require some help here...

This happens when you open customization dialog (dbl click toolbar) and move the buttons around (only on toolbar, not in the dialog itself).


About the relevant code:
Everything is happeing in the Toolbar_OnNotify function.
I am am compiling the ALL variable holding all buttons into TBBUTTON array when customization dialog is first open. On succesive notifications via TBN_GETBUTTONINFOA message , I copy the requested item from this array into buffer Toolbar control alocated (lparam + 16 and also copy the buttons text into another buffer (pszText) as requested by TBN_GETBUTTONINFOA.

Reference:
TBN_GETBUTTONINFOA
http://msdn2.microsoft.com/en-us/library/bb787266(VS.85).aspx

NMTOOLBAR
http://msdn2.microsoft.com/en-us/library/bb760473(VS.85).aspx

Sample
http://msdn2.microsoft.com/en-us/library/bb760446(VS.85).aspx#Customizing_Toolbars


To do
- Notification interface
- Save/Restore of toolbar
_________________


Last edited by majkinetor on Tue Jan 29, 2008 10:01 am; edited 1 time in total
Back to top
View user's profile Send private message MSN Messenger
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Sat Jan 12, 2008 10:05 pm    Post subject: Reply with quote

Some more tests to present posibilities. Toolbars are added to Static (text) containers instead of main gui. This allows toolbar to be positioned anywhere in the main gui. Container needs to be subclassed to handle WM_NOTIFY messages from toolbar. Currently it doesn't work with flat toolbars correctly, as it shows black background (don't know why, related but doesn't depend on themes here). I put border around statics so you can see containers.

In containers


Vertical (wrapped with fixed button and container width


In Rebar, 2 vertical toolbars


Toolbar is added into rebar also using Static container as for some reason it doesn't accept toolbar control directly (don't know why)

Here are scripts to play with.
_________________
Back to top
View user's profile Send private message MSN Messenger
skwire



Joined: 18 Jan 2006
Posts: 150
Location: Conway, Arkansas

PostPosted: Sat Jan 12, 2008 10:43 pm    Post subject: Reply with quote

This is really fantastic, majkinetor. Thank you for putting this together and continuing to work on it.
Back to top
View user's profile Send private message AIM Address Yahoo Messenger MSN Messenger
Lexikos



Joined: 17 Oct 2006
Posts: 2602
Location: Australia, Qld

PostPosted: Sun Jan 13, 2008 4:37 am    Post subject: Reply with quote

Very nice work! Very Happy
majkinetor wrote:
This is the picture of the bug that I can't manage to fix. Perhaps I don't see something, so I require some help here...
On my system the squares show as Japanese characters. Laughing It seems the toolbar is messing up (maybe deleting the text or invalidating the pointer), referencing garbage where the text used to be.

The solution is to let the toolbar manage all strings, rather than giving it string pointers.

Require hToolbar as a parameter for Toolbar_compileButtons, then instead of
Code:
VarSetCapacity(buf, 64*cnt)
tp := &Buf
...
DllCall("lstrcpyn", "uint", tp, "uint", &a1, "int", 64)
use
Code:
VarSetCapacity(buf, StrLen(a1)+1, 0), buf:=a1
tp:=DllCall("SendMessage","uint",hToolbar,"uint",0x41C,"uint",0,"uint",&buf) ; TB_ADDSTRING
Buf must be double-NULL-terminated, hence the "+1, 0". TB_ADDSTRING returns the new index of the string within the string pool.

It seems there aren't any messages for removing or changing a string in the string pool... Sad hopefully I'm overlooking something. Well, I suppose you wouldn't commonly want to change a button's text.

Perhaps you could instead update the strings in response to TBN_TOOLBARCHANGE.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Sun Jan 13, 2008 12:36 pm    Post subject: Reply with quote

Hej, that works Very Happy

But I wonder

I wonder, perhaps it is seeing my text pointers as sting pull index for some reason...
Quote:
The iString member can return either a string pointer or an index. You can use the err! bad xref: _win32_IS_INTRESOURCE [rid not found (_win32_IS_INTRESOURCE).] macro to determine which is returned.


Quote:
It seems there aren't any messages for removing or changing a string in the string pool... hopefully I'm overlooking something. Well, I suppose you wouldn't commonly want to change a button's text.

I wouldn't like such limitation as you can use toolbar unconventionaly in many scenarios. You can still change text with SetButtonInfo, but that doesn't change the string pool :
Code:
   Toolbar_SetButtonInfo( hToolbar, 1, "button 1")

This will change the text for the button1 but old text "btn1" will be returned in customization dialog.

Quote:
Text is commonly assigned to buttons when they are added to a toolbar by specifying the index of a string in the toolbar's string pool. If you use a TB_SETBUTTONINFO to assign new text to a button, it will permanently override the text from the string pool. You can change the text by calling TB_SETBUTTONINFO again, but you cannot reassign the string from the string pool.


So, its not possible to change the string pull. Changing the text is possible, but not in customization dialog, wich is minor limitation IMO. However, customization dialog can be changed by chaging the ALL global variable in sync with changing the button's text Smile. So in the above statement, along with SetButonInfo call there should be call that sets "button 1" as text for the first button in ALL var, and customization dlg will be updated well.

I would be more lucky to made previous solution working, but as I can't, I will switch to this one. I wonder how that MSDN sample works without problems, I was totaly following it...

Quote:
Perhaps you could instead update the strings in response to TBN_TOOLBARCHANGE.

Yes, definitely an option.


Thank you Lex, you were very helpfull as always.


BTW, In the meantime, I discovered that using entire GUI as container for the toolbar (and then SetParent) doesn't introduce transparaency problem (black background). Adding GUI strate from the AHK makes parent GUI unable to focus, but I guess it can be fixed by constructing the container from the bottom up using RegisterClass and CWEx.
_________________
Back to top
View user's profile Send private message MSN Messenger
Lexikos



Joined: 17 Oct 2006
Posts: 2602
Location: Australia, Qld

PostPosted: Sun Jan 13, 2008 1:33 pm    Post subject: Reply with quote

majkinetor wrote:
I wonder, perhaps it is seeing my text pointers as sting pull index for some reason...
Sounds like a possibility.
majkinetor wrote:
Quote:
The iString member can return either a string pointer or an index. You can use the err! bad xref: _win32_IS_INTRESOURCE [rid not found (_win32_IS_INTRESOURCE).] macro to determine which is returned.
Shocked ?
My sane copy of MSDN wrote:
The iString member can return either a string pointer or an index. You can use the IS_INTRESOURCE macro to determine which is returned.
Code:
#define IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0)

majkinetor wrote:
Adding GUI strate from the AHK makes parent GUI unable to focus,
Sounds like what happens when you SetParent() without removing WS_POPUP and adding WS_CHILD...
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3626
Location: Belgrade

PostPosted: Sun Jan 13, 2008 1:59 pm    Post subject: Reply with quote

Quote:
My sane copy of MSDN wrote:

ROFLMAO.
I was wondering wht the heck is that...

Quote:
Sounds like what happens when you SetParent() without removing WS_POPUP and adding WS_CHILD...

Good, I tried that, but I probably messed it up in WinSpector...

So now it works

Sample:
Code:
#SingleInstance, force
SetBatchLines, -1
    #Include ShowMenu.ahk
   Gui, +LastFound +LabelMyGui
;   Gui, Add, text, hwndhS1 w400 h50 border
;   Gui, Add, text, hwndhS2 w50 h300 border
;   Gui, Add, text, hwndhS3 x100 y100 w100 h100 border
;
;   Subclass( hS1, "MyWindowProc" )
;   Subclass( hS2, "MyWindowProc" )
;   Subclass( hS3, "MyWindowProc" )

   hwnd := WinExist()
   Gui, Show , w400 h250      ;set gui width & height (mandatory)

   hIL := IL_Create(5, 0, 1)


   Gui, 2:+LastFound -Caption
   Gui, 2:Show ,w300 h100 Hide NoActivate
   h := WInExist()

   hToolbar := Toolbar_Add(h)
   Toolbar_SetImageList(hToolbar)

   btns =
   (LTrim
      btn1
      btn2
      btn3
      btn3
      btn1
      btn2
      btn3
      btn3
   )

   Gui 2:Show, x50 y100 w300 h100 NoActivate
    Toolbar_AddButtons(hToolbar, btns)
   DllCall("SetParent", "uint", h, "uint", hwnd)
   WinSet, Style, -0x80000000, ahk_id %h%      ;   WS_POPUP=0x80000000
   WinSet, Style, +0x40000000, ahk_id %h%      ;   WS_CHILD=0x40000000
   Gui, show
return   

MyWindowProc(hwnd, uMsg, wParam, lParam){
   if uMsg = 0x4E
      return Toolbar_OnNotify(wparam, lparam)

   return DllCall("CallWindowProcA", "UInt", A_EventInfo, "UInt", hwnd, "UInt", uMsg, "UInt", wParam, "UInt", lParam)
}

;------------------------------------------------------------------------------
;Compile btn definition into binary array. Return number of button.
;  aBTN - compiled btn array
;  Buf   - buffer for btn text
;  btns - textual btn def
;
Toolbar_compileButtons(ByRef aBTN, ByRef buf, btns) {
   static BTNS_SEP=1, BTNS_CHECK =2, BTNS_CHECKGROUP = 6, BTNS_DROPDOWN = 8, BTNS_A=16, BTNS_AUTOSIZE = 16, BTNS_NOPREFIX = 32, BTNS_SHOWTEXT = 64
   static TBSTATE_CHECKED=1, TBSTATE_ENABLED=4, TBSTATE_HIDDEN=8, TBSTATE_GRAYED =16, TBSTATE_PRESSED =5, TBSTATE_CLICKED=6, TBSTATE_WRAP=32, TBSTATE_ELLIPSES=0x40
   static TB_ADDBUTTONSA = 0x414, TB_AUTOSIZE=0x421
   
   StringReplace, _, btns, `n, , UseErrorLevel
   cnt := ErrorLevel + 1
   sep := 0

   VarSetCapacity(aBTN, 20*cnt, 0)
   VarSetCapacity(buf, 64*cnt)
   tp := &Buf
   loop, parse, btns, `n
   {
      a1:=a2:=a3:=a4:=""
      StringSplit, a, A_LoopField, |
      hstate := TBSTATE_ENABLED
      loop, parse, a3, %A_Tab%%A_Space%, %A_Tab%%A_Space%
      {
         ifEqual, A_LoopField,,continue
         hstate |= TBSTATE_%A_LOOPFIELD%
      }
      hstyle := A_LoopField = "-" ? BTNS_SEP : BTNS_SHOWTEXT
      if (hstyle = BTNS_SEP)
         sep+=1

      loop, parse, a4, %A_Tab%%A_Space%
      {
         ifEqual, A_LoopField,,continue
         hstyle |= BTNS_%A_LOOPFIELD%
      }
      
      if a2 is not Integer      ;if user doesn't specify icon, use A_Index, but don't count separators
         a2 := A_Index - sep

      o := &aBTN + 20*(A_Index-1)

      DllCall("lstrcpyn", "uint", tp, "uint", &a1, "int", 64)
      NumPut(a2-1,   o+0, 0)               ;id
      NumPut(A_Index, o+0, 4)      ;id
      NumPut(hstate,  o+0, 8, "Char")
      NumPut(hStyle,  o+0, 9, "Char")
      NumPut(tp,      o+0, 16)
      tp += StrLen(a1)+1
   }
   return cnt
}

Toolbar_onNotify(wparam, lparam) {
    local hwnd, id, code, txt
   static NM_CLICK=-2, TBN_DROPDOWN = -710, TBN_HOTITEMCHANGE = -713, TBN_BEGINADJUST=-703, TBN_GETBUTTONINFOA=-700, TBN_QUERYINSERT=-706, TBN_QUERYDELETE=-707, TBN_ENDADJUST=-704, TBN_DELETINGBUTTON=-715, TBN_RESET=-705, TBN_TOOLBARCHANGE=-708
   static cus, cntAll

 ;NMHDR
   hwnd   :=  NumGet(lparam+0)   ;control sending the message - this toolbar
;   idFrom :=  NumGet(lparam+4)   ; and its ID
    code   :=  NumGet(lparam+8) - 4294967296

 ;TOOLBAR
   iItem  :=  NumGet(lparam+12)

   if (code = NM_CLICK) and (iItem != 4294967295){
      txt := Toolbar_GetButtonInfo( hwnd, iItem )
      tooltip  %txt% :  %iItem% click
      return
   }

   if (code = TBN_DROPDOWN){
      ShowMenu("[1]`ntext1`ntext2`ntext31111111111", "", "mnu")
      return
   }

   if (code = TBN_HOTITEMCHANGE){
      iItem := NumGet(lparam+16)
;      tooltip % Toolbar_GetButtonInfo(htoolbar, iItem)
      return
   }

   TBB := lparam + 16
   if (code = TBN_GETBUTTONINFOA){
      if !cus {
         cntAll := Toolbar_compileButtons(aBTNS, NBUF, all ), cus := true
      }
      if (iItem = cntAll)      ;iItem is position, not identifier
         return
   
      o := &aBTNS + 20*iItem,    TBB := lparam +16


      DllCall("MSVCRT\memcpy", "UInt", TBB, "UInt", o, "uint", 20) ;copy the compiled item into notification struct

      ;Customization dialog uses this buffer to get text to display.
      ;It doesn't use TBB+16, probably because text can be some longer tooltip, if you specified TOOLTIPS flag.
      DllCall("MSVCRT\memcpy", "UInt", NumGet(TBB+24), "UInt", NumGet(o+16), "uint", NumGet(TBB+20) )
      return TRUE
   }

   ;Return at least one TRUE here to show the dialog, if the dialog is openinig
   ;When the dialog is open, it affects btn addition
   if (code= TBN_QUERYINSERT) {
      return TRUE
;      if !cus
;         return TRUE
;      else {
;        ; tooltip %iItem%
;         return TRUE
;      }
   }

   ;existing items can not be deleted if TRUE is not returned here
   if (code= TBN_QUERYDELETE) {
;      if iItem in 0,1,2   ;   prevent 0,1,2 id's to be deleted
;         return FALSE
      return TRUE
   }

   if (code=TBN_ENDADJUST){
      return
   }
}

F12::
   stop := 1
;   HexView(&NBUF, 100)
;   hexview(NumGet(o+16), 20)
return

Toolbar_AddButtons(hToolbar, btns){   
   static TB_ADDBUTTONSA = 0x414, TB_AUTOSIZE=0x421
   
   cnt := Toolbar_compileButtons(aBTN, TextBuf, btns)
   SendMessage, TB_ADDBUTTONSA, cnt, &aBTN ,, ahk_id %hToolbar%
   SendMessage, TB_AUTOSIZE, , ,,ahk_id %hToolbar%
}


Toolbar_Add(hGui, style="WRAPABLE FLAT ADJUSTABLE") {
   static TOOLBARCLASSNAME  = "ToolbarWindow32" 
   static WS_CHILD := 0x40000000, WS_VISIBLE := 0x10000000, WS_CLIPSIBLINGS = 0x4000000, WS_CLIPCHILDREN = 0x2000000
   static TBSTYLE_EX_DRAWDDARROWS = 0x1, TBSTYLE_EX_HIDECLIPPEDBUTTONS=0x10, TBSTYLE_EX_MIXEDBUTTONS=0x8   ;extended styles
    static TBSTYLE_WRAPABLE = 0x200, TBSTYLE_FLAT = 0x800, TBSTYLE_LIST=0x1000, TBSTYLE_TOOLTIPS=0x100, TBSTYLE_TRANSPARENT = 0x8000
   static TBSTYLE_BORDER=0x800000, TBSTYLE_ADJUSTABLE = 0x20
   static init, TB_BUTTONSTRUCTSIZE=0x41E, TB_SETEXTENDEDSTYLE := 0x454, TB_SETUNICODEFORMAT := 0x2005

   hStyle := 0
   loop, parse, style, %A_Tab%%A_Space%, %A_Tab%%A_Space%
   {
      ifEqual, A_LoopField,,continue
      hStyle |= A_LoopField+0 ? A_LoopField : TBSTYLE_%A_LoopField%
   }

    if !init  {
      OnMessage(WM_NOTIFY := 0x4E, "Toolbar_onNotify"), init := true
   }
   
    hToolbar := DllCall("CreateWindowEx"
             , "uint", 0
             , "str",  TOOLBARCLASSNAME
             , "uint", 0
             , "uint", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | hStyle
             , "uint", 0, "uint", 0, "uint", 0, "uint", 0
             , "uint", hGui
             , "uint", 0
             , "uint", 0
             , "uint", 0, "Uint")
    ifEqual, hToolbar, 0, return "Err: can't create toolbar"
   
   SendMessage, TB_BUTTONSTRUCTSIZE, 20, 0, , ahk_id %hToolbar%
   SendMessage, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS|TBSTYLE_EX_MIXEDBUTTONS, , ahk_id %hToolbar%
   SendMessage, TB_SETUNICODEFORMAT, 0, 0, , ahk_id %hToolbar%        ;set to ANSI
    return hToolbar
}

Toolbar_SetImageList(hToolbar, hIL="1L"){
   static TB_SETIMAGELIST=0x430, TB_LOADIMAGES=0x432, TB_SETBITMAPSIZE=0x420

   if hIL is Integer
      SendMessage, TB_SETIMAGELIST, 0, hIL, ,ahk_id %hToolbar%
   else  {

      size := SubStr(hIL,2,1)="L" ? 24:16,  cat := (SubStr(hIL, 1,1)-1)*4 + (size=16 ? 0:1)
      Toolbar_SetBitmapSize(hToolbar, size, size)
      SendMessage, TB_LOADIMAGES, cat, -1,,ahk_id %hToolbar%
   }
   return ErrorLevel
}


;----------------------------------------------------------------------------------------------
;Function:  SetButtonInfo
;         Set button information
;
;Parameters:
;         hToolbar   - HWND of the toolbar
;         id         - Button identification (currently equal to buttons position)
;         text      - Text to set for the button. If "" text will not be changed. If "-" text wil be removed (the same as omiting both text and state parameters)
;         state      - List of button states to set, separated by white space. See bellow.
;
; Button states:
;         CHECKED, ENABLED, HIDDEN, GRAYED, PRESSED, CLICKED
;
; Returns:
;         Nonzero if successful, or zero otherwise.
;
Toolbar_SetButtonInfo(hToolbar, id, text="", state="", width=""){
   static TB_SETBUTTONINFO=0x442, TBIF_TEXT=2, TBIF_STATE=4, TBIF_SIZE=0x40, TB_AUTOSIZE=0x421
   static TBSTATE_CHECKED=1, TBSTATE_ENABLED=4, TBSTATE_HIDDEN=8, TBSTATE_GRAYED=16, TBSTATE_PRESSED=5, TBSTATE_CLICKED=6, TBSTATE_WRAP=32

   hstate := 0
   loop, parse, state, %A_Tab%%A_Space%, %A_Tab%%A_Space%
   {
      ifEqual, A_LoopField,,continue
      hstate |= TBSTATE_%A_LOOPFIELD%
   }

   mask := 0
   mask |= text != "" ?  TBIF_TEXT : 0
   mask |= state!= "" ?  TBIF_STATE : 0
   mask |= width!= "" ?  TBIF_SIZE : 0

   if text = -
      text =
   if (state text = "")
      mask := TBIF_TEXT, text := ""

   VarSetCapacity(BI, 32, 0)
   NumPut(32, BI, 0)
   NumPut(mask, BI, 4)
   NumPut(hstate, BI, 16, "Char")
   NumPut(width, BI, 18, "Short")
   NumPut(&text, BI, 24)
    SendMessage, TB_SETBUTTONINFO, id, &BI, ,ahk_id %hToolbar%
   res := ErrorLevel
   SendMessage, 0x421, , ,,ahk_id %hToolbar%   ;autosize
   return res
}



;----------------------------------------------------------------------------------------------
;Function:  SetButtons
;         Set all butons at once using textual definition
;
;Parameters:
;         hToolbar   - HWND of the toolbar
;         info      - Textual definition of buttons info. For each button there should be line containg *text|state list* where
;                    both _text_ and _state list_ are optional. You can also use "-" to skip button (the same as empty line).
;                    If you omit this parameter text and state for each button will be cleared
;
Toolbar_SetButtons(hToolbar, info=""){
   if info=
   {
      Loop, % Toolbar_GetButtonCount(hToolbar)
         Toolbar_SetButtonInfo(hToolbar, A_Index, "-", "ENABLED" )
      return
   }

   loop, parse, info, `n,
   {
      if j := InStr(A_LoopField, "|")
         state := SubStr(A_LoopField, j+1)
      else state := "enabled"
      txt := SubStr(A_LoopField, 1, j ? j-1 : 99)
      ifEqual txt, -, continue


      Toolbar_SetButtonInfo(hToolbar, A_Index, txt, state)
   }
}

;----------------------------------------------------------------------------------------------
;Function:  GetButtonInfo
;         Get button information
;
;Parameters:
;         hToolbar   - HWND of the toolbar
;         id         - ID of the button (currently the same as position)
;         info      - What kind of info to return - text (default) or state
;
Toolbar_GetButtonInfo(hToolbar, id, info="text"){
;   static TB_GETBUTTONINFO=0x441, TBIF_TEXT=2, TBIF_STATE=4
   static TB_GETBUTTONTEXT=0x42D, TB_GETSTATE=0x412
   static S1 = "CHECKED", S4 = "ENABLED", S8 ="HIDDEN", S16="GRAYED", S5="PRESSED", S6="CLICKED"

   if info=text
   {
      VarSetCapacity( buf, 128 )
      SendMessage, TB_GETBUTTONTEXT,id,&buf,,ahk_id %hToolbar%
      ifEqual, Errorlevel, 4294967295, return
      VarSetCapacity( buf, -1 )
      return buf
   }
   else if info=state
   {
        SendMessage, TB_GETSTATE,id,,,ahk_id %hToolbar%
      state = S%ErrorLevel%
      state := %state%
      return state
   }

;   mask := TBIF_TEXT
;   if info = state
;      mask := TBIF_STATE
;      
;
;   VarSetCapacity(BI, 32, 0)
;   NumPut(32, BI, 0)
;   NumPut(mask, BI, 4)
;    SendMessage, TB_GETBUTTONINFO, id, &BI, ,ahk_id %hToolbar%
;   if ErrorLevel=4294967295
;      return "Err: can't get button info"
;
;   if info=text
;      return NumGet(BI, 8)


}

;----------------------------------------------------------------------------------------------
;Function:  GetButtonCount
;         Get count of buttons on the toolbar
;
;Parameters:
;         hToolbar   - HWND of the toolbar
;
;Returns:
;         Count
Toolbar_GetButtonCount(hToolbar) {
   static TB_BUTTONCOUNT = 0x418
    SendMessage, TB_BUTTONCOUNT, , , ,ahk_id %hToolbar%
   return ErrorLevel
}

;----------------------------------------------------------------------------------------------
;Function:  DeleteButton
;         Delete button from the toolbar
;
;Parameters:
;         hToolbar   - HWND of the toolbar
;         idx         - 1-based position of the button
;
;Returns:
;         TRUE if successful, or FALSE otherwise.
;
Toolbar_DeleteButton(hToolbar, idx=1) {
   static TB_DELETEBUTTON = 0x416
    SendMessage, TB_DELETEBUTTON, idx-1, , ,ahk_id %hToolbar%
   return ErrorLevel
}


;----------------------------------------------------------------------------------------------
;Function:  GetRect
;         Get button rectangle
;
;Parameters:
;         hToolbar   - HWND of the toolbar
;         id         - Button id
;
;Returns:
;         String with 4 rect values, separated by space
;
Toolbar_GetRect(hToolbar, id) {
   static TB_GETRECT=0x433, RECT

   VarSetCapacity(RECT, 16)
    SendMessage, TB_GETRECT, id,&RECT, ,ahk_id %hToolbar%
   IfEqual, ErrorLevel, 0, return "Err: can't get rect"

   return NumGet(RECT, 0) " " NumGet(RECT, 4) " " NumGet(RECT, 8) " " NumGet(RECT, 12)
}

;----------------------------------------------------------------------------------------------
;Function:  GetRows
;         Get number of toolbar rows
;
;Parameters:
;         hToolbar   - HWND of the toolbar
;
;Returns:
;         Count
;
Toolbar_GetRows(hToolbar) {
   static TB_GETROWS=0x428
    SendMessage, TB_GETROWS,,,,ahk_id %hToolbar%
   return ErrorLevel-1
}
   
;doesn't work correctly for some reason
Toolbar_SetPadding(hToolbar, cx=6, cy=7) {
   static TB_SETPADDING=0x457

    SendMessage, TB_SETPADDING,0,(cx<<16)+cy,,ahk_id %hToolbar%
   return ErrorLevel>>16 " " ErrorLevel & 0xFFFF
}

mnu:
      Toolbar_SetButtonInfo(hToolbar, id, A_ThisMenuItem)
return

Toolbar_SetDrawTextFlags(hToolbar) {
   static TB_SETDRAWTEXTFLAGS = 0x446
}

;Returns nonzero if successful, or zero otherwise.
Toolbar_SetMaxTextRows(hToolbar, iMaxRows=0) {
   static TB_SETMAXTEXTROWS = 0x43C
    SendMessage, TB_SETMAXTEXTROWS,iMaxRows,,,ahk_id %hToolbar%
   res := ErrorLevel
    SendMessage,0x421,,,,ahk_id %hToolbar% ;autoresize
   return res
}

Toolbar_SetMetrics(hToolbar, xPad="", yPad="", xButtonMargin="", yButtonMargin="", xMargin="", yMargin=""){
    VarSetCapacity(met,32,0), NumPut(32,met)
    NumPut( ((xPad yPad)!="" ? 1:0)
        | ((xMargin yMargin)!="" ? 2:0)
        | ((xButtonMargin yButtonMargin)!="" ? 4:0), met, 4)
    NumPut(xPad,met,8), NumPut(yPad,met,12)
    NumPut(0,met,16), NumPut(yMargin,met,20)
    NumPut(xButtonMargin,met,24), NumPut(yButtonMargin,met,28)
    DllCall("SendMessage","uint",hToolbar,"uint",0x466,"uint",0,"uint",&met) ; TB_SETMETRICS
    DllCall("SendMessage","uint",hToolbar,"uint",0x42F,"int",xMargin,"uint",0) ; TB_SETINDENT
}

;Returns TRUE if successful, or FALSE otherwise.
Toolbar_SetButtonSize(hToolbar, x=0, y=0) {
   static TB_SETBUTTONSIZE = 0x41F

   SendMessage, TB_SETBUTTONSIZE, 0,(y<<16) | x,,ahk_id %hToolbar%
   SendMessage, 0x421, , ,,ahk_id %hToolbar%   ;autosize
}

;Returns nonzero if successful, or zero otherwise.
Toolbar_SetButtonWidth(hToolbar, cxMin, cxMax ){
   static TB_SETBUTTONWIDTH=0x43B

   SendMessage, TB_SETBUTTONWIDTH, 0,(cxMin<<16) | cxMax,,ahk_id %hToolbar%
   return Errorlevel
}

Toolbar_SetBitmapSize(hToolbar, x, y ) {
   SendMessage, 0x420,0,(x<<16)+y, , ahk_id %hToolbar%
}

Toolbar_AutoSize(hToolbar){
    SendMessage,0x421,,,,ahk_id %hToolbar% ;autoresize
}


;-------------------------------------------------------------------------------------------------------------------
;Group: Example
;
;>   Gui, +LastFound
;>   hwnd := WinExist()
;>   Gui, Show ,w280 h200      ;set gui width & height (mandatory)
;>    hToolbar := Toolbar_Add(hwnd)

;-------------------------------------------------------------------------------------------------------------------
;Group: About
;      o Ver 1.0 b1 by majkinetor. See http://www.autohotkey.com/forum/topic27382.html
;      o Toolbar Reference at MSDN: <http://msdn2.microsoft.com/en-us/library/bb760435(VS.85).aspx>
;      o Licenced under Creative Commons Attribution-Noncommercial <http://creativecommons.org/licenses/by-nc/3.0/>.

MyGuiClose:
MyGuiEscape:
   exitapp
return

;-------------------------------------------------------------------------------------
; Function: Subclass
;         Helper function to subclass control
;
; Parameters:
;         hCtrl   - handle to control
;         func   - window procedure
;         cbOpt   - callback options, by default ""
;
Subclass(hCtrl, func, cbOpt="") {
   oldProc := DllCall("GetWindowLong", "uint", hCtrl, "uint", -4)
   ifEqual, oldProc, 0, return 0
       
   WndProc := RegisterCallback(func, cbOpt, 4, oldProc)
   ifEqual, WndProc, , return 0
       
    return DllCall("SetWindowLong", "UInt", hCtrl, "Int", -4, "Int", WndProc, "UInt")
}




It still makes sense to create container window from ground up just to avod using new gui, every time you need this feature (and its obviously very useful)
_________________
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group