Introduction:
In this tutorial we'll see about Toolbars, creating a basic toolbar.Toolbar is just a control with one or more buttons in it when any button clicked WM_COMMAND message is send to parent window.
A toolbar can be created by using CreateWindowEx function or CreateToolbarEx function or prefer a resource editor.It is important to pass 'ToolbarWindow32' as class name while preferring CreateWindowEx.
The toolbar window automatically adjusts the size of the toolbar by recieving TB_AUTOSIZE message.we use TB_ADDBITMAP to list our button images for our toolbar. so that we can access by index of the bitmap image starting from zero.
After the toolbar is created we can add buttons by TB_INSERTBUTTON or by using TB_ADDBUTTONS message. If toolbar created by CreateWindowEx TB_BUTTONSTRUCTSIZE message should be send to our toolbar with lParam size of our TBBUTTON structure.
The main task here is to fill the members of TBBUTTON struct and TBADDBITMAP struct
TBBUTTON STRUCT
iBitmap DWORD ?
idCommand DWORD ?
fsState BYTE ?
fsStyle BYTE ?
dwData DWORD ?
iString DWORD ?
TBBUTTON ENDS
iBitmap -> Index of the button Image starting from zero. The bitmap listed by using TB_ADDBITMP message.
idCommand -> Command identifier associated with the button.we use this identifier in WM_COMMAND message when button is chosen.
fsState -> Button state flags. we use TBSTATE_ENABLED here.
fsStyle -> Button style. we often use TBSTYLE_SEP for seperator,TBSTYLE_BUTTON for button.
dwData -> Index of the Button string starting from zero,we don't use it here.
TBADDBITMAP STRUCT
hInst DWORD ?
nID DWORD ?
TBADDBITMAP ENDS
hInst -> we use system-defined button bitmaps by specifying HINST_COMMCTRL as the hInst member but if we use our own bitmap images this should be zero.
nIdD -> If we use our own bitmap this should be the handle to the bitmap image, In case if you use system defined you can use the below values.
IDB_STD_LARGE_COLOR -Adds large, color standard bitmaps.
IDB_STD_SMALL_COLOR -Adds small, color standard bitmaps.
IDB_VIEW_LARGE_COLOR -Adds large, color view bitmaps.
IDB_VIEW_SMALL_COLOR -Adds small, color view bitmaps.
First using CreateToolbarEx and using system defined toolbar images.
DlgProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM LOCAL tbb :TBBUTTON LOCAL Tba :TBADDBITMAP .if uMsg==WM_INITDIALOG invoke CreateToolbarEx,hWnd,WS_CHILD or WS_CLIPSIBLINGS or TBSTYLE_FLAT , 300,0,0,0,ADDR tbb,1,16,16,0,0,sizeof TBBUTTON mov hToolBar, eax invoke ShowWindow,hToolBar,SW_SHOW invoke RtlZeroMemory,addr Tba,sizeof TBADDBITMAP invoke RtlZeroMemory,addr tbb,sizeof TBBUTTON ;The unchanging data till end of program mov tbb.fsState, TBSTATE_ENABLED mov tbb.dwData, 0 mov tbb.iString, 0 ;fill toolbar add bitmap struct mov Tba.hInst, HINST_COMMCTRL mov Tba.nID,IDB_STD_LARGE_COLOR invoke SendMessage,hToolBar,TB_ADDBITMAP,1,ADDR Tba ;a seperator mov tbb.iBitmap, 0 mov tbb.idCommand, 0 mov tbb.fsStyle, TBSTYLE_SEP invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb ;new button mov tbb.iBitmap,STD_FILENEW mov tbb.fsStyle, TBSTYLE_BUTTON mov tbb.idCommand, 50 invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb ;open button mov tbb.iBitmap,STD_FILEOPEN mov tbb.idCommand, 51 mov tbb.fsStyle, TBSTYLE_BUTTON invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb ;save button mov tbb.iBitmap,STD_FILESAVE mov tbb.idCommand, 52 mov tbb.fsStyle, TBSTYLE_BUTTON invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb .elseif uMsg==WM_SIZE invoke SendMessage,hToolBar,TB_AUTOSIZE,0,0 .elseif uMsg==WM_COMMAND .if wParam==50 invoke MessageBox,hWnd,addr new,addr AppName,MB_OK .elseif wParam==51 invoke MessageBox,hWnd,addr open,addr AppName,MB_OK .elseif wParam==52 invoke MessageBox,hWnd,addr save,addr AppName,MB_OK .endif .elseif uMsg==WM_CLOSE invoke DeleteObject,hTbBmp invoke EndDialog,hWnd,0 .else mov eax,FALSE ret .endif mov eax,TRUE Ret DlgProc endp
Explanation:
In our dialog procedure we define two structures on stack. The details about structures discussed above,
invoke CreateToolbarEx,hWnd,WS_CHILD or WS_CLIPSIBLINGS or TBSTYLE_FLAT , 300,0,0,0,ADDR tbb,1,16,16,0,0,sizeof TBBUTTON mov hToolBar, eax invoke ShowWindow,hToolBar,SW_SHOW invoke RtlZeroMemory,addr Tba,sizeof TBADDBITMAP invoke RtlZeroMemory,addr tbb,sizeof TBBUTTON mov tbb.fsState, TBSTATE_ENABLED mov tbb.dwData, 0 mov tbb.iString, 0 mov Tba.hInst, HINST_COMMCTRL mov Tba.nID,IDB_STD_LARGE_COLOR invoke SendMessage,hToolBar,TB_ADDBITMAP,1,ADDR Tba
We create our toolbar,including WS_CHILD in window style is compulsory, TBSTYLE_FLAT to make it flat else the buttons would be bulging out. Then store the handle. we display our window just created we can also include WS_VISIBLE in window styles which eliminate the need for the line.Before using structures we should zero especially if the structure is in stack our program would crash.(thanks to GunnerInc) we use RtlZeroMemory to fill our memory with zeros
Then fill the unchanging members in our TBBUTTON structure. TBSTATE_ENABLED to make the toolbar accept user input.Remaining are zero since we dont use it.
Then fill TBADDBITMAP structure we use HINST_COMMCTRL so we can use system defined button images.In the nID member we have four options discussed above.
Then we set bitmap for our toolbar by sending TT_ADDBITMAP message, We don't need to send message TB_BUTTONSTRUCTSIZE since we use CreateToolbarEx function.
mov tbb.iBitmap, 0 mov tbb.idCommand, 0 mov tbb.fsStyle, TBSTYLE_SEP invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb ;new button mov tbb.iBitmap,STD_FILENEW mov tbb.fsStyle, TBSTYLE_BUTTON mov tbb.idCommand, 50 invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb ;open button mov tbb.iBitmap,STD_FILEOPEN mov tbb.idCommand, 51 mov tbb.fsStyle, TBSTYLE_BUTTON invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb ;save button mov tbb.iBitmap,STD_FILESAVE mov tbb.idCommand, 52 mov tbb.fsStyle, TBSTYLE_BUTTON invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb
Then time to create buttons in our controls. First is a seperator so in fsStyle we use TBSTYLE_SEP. Then we add buttons by sending TB_ADDBUTTONS message. Then buttons in our toolbar iBitmap we use STD_FILENEW which use system defined file new icon. And we set a command identifier to let us know the from which button message is send. Then we use TB_ADDBUTTONS message to set our buttons in toolbar. Similarly we do it for other other buttons.
.elseif uMsg==WM_SIZE invoke SendMessage,hToolBar,TB_AUTOSIZE,0,0 .elseif uMsg==WM_COMMAND .if wParam==50 invoke MessageBox,hWnd,addr new,addr AppName,MB_OK .elseif wParam==51 invoke MessageBox,hWnd,addr open,addr AppName,MB_OK .elseif wParam==52 invoke MessageBox,hWnd,addr save,addr AppName,MB_OK .endif .elseif uMsg==WM_CLOSE invoke DeleteObject,hTbBmp invoke EndDialog,hWnd,0
We use the WM_SIZE message to resize the toolbar ,TB_AUTOSIZE message causes a toolbar to adjust the toolbar size automatically.When the user selects a button, the toolbar sends the parent window a WM_COMMAND message that includes the command identifier of the button wParam contains the command identifier. Using it we can respond to messages properly. We must call the DeleteObject function to delete bitmap handle returned by the LoadBitmap function.
Using CreateWindowEx function and using our own toolbar images
In order to ease our work and reduce repetition of the code we use macros here. One of the great advantages of assemblers is macros. Macros can be used to replace typing of same code again and again,The Syntax for macro is
Syntax: name MACRO [parameter[:tag]] [,parameter[:tag]]...] [LOCAL varlist] statements [EXITM [textitem]] ENDM
name-Name of our macro
parameter- values passed for our macro function
statements -our usual assembler instructions
TBextraData MACRO mov tbb.fsState, TBSTATE_ENABLED mov tbb.dwData, 0 mov tbb.iString, 0 ENDM ; ------------------------------ TBbutton MACRO bID, cID mov tbb.iBitmap, bID ;button ID mov tbb.idCommand, cID ;command ID mov tbb.fsStyle, TBSTYLE_BUTTON invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb ENDM ; ------------------------------ TBblank MACRO mov tbb.iBitmap, 0 mov tbb.idCommand, 0 mov tbb.fsStyle, TBSTYLE_SEP invoke SendMessage,hToolBar,TB_ADDBUTTONS,1,ADDR tbb ENDM
TBextraData MACRO for the unchanging data in the program till end of the program.TBblank MACRO for inserting a blank seperator in our toolbar and TBbutton MACRO which recieves two values and add button to our toolbar.
To use our own toolbar images we have to define a resource identifier for our image and load our bitmap using LoadBitmap function and use a special procedure to make some adjustments to our image. Since we use our own toolbar images we have to set our bitmap size using TB_SETBITMAPSIZE message and set button size using TB_SETBUTTONSIZE message.
mov ecx,16 ; Width mov eax,15 ; Height shl eax,16 mov ax, cx mov bSize, eax invoke SendMessage,hToolBar,TB_SETBITMAPSIZE,0,bSize invoke SendMessage,hToolBar,TB_SETBUTTONSIZE,0,bSize
We use 16 by 15 sized bitmap image. So we got to set our bitmap size and button size we shift 16 bits left and free the low word of eax and move the low word of ecx in the free space shifted. and use the value to set bitmap size and button size. Then use our special procedure.
SetBmpColor proc hBitmap:DWORD LOCAL mDC :DWORD LOCAL hBrush :DWORD LOCAL hOldBmp :DWORD LOCAL hReturn :DWORD LOCAL hOldBrush :DWORD invoke CreateCompatibleDC,NULL mov mDC,eax invoke SelectObject,mDC,hBitmap mov hOldBmp,eax invoke GetSysColor,COLOR_BTNFACE invoke CreateSolidBrush,eax mov hBrush,eax invoke SelectObject,mDC,hBrush mov hOldBrush,eax invoke GetPixel,mDC,1,1 invoke ExtFloodFill,mDC,1,1,eax,FLOODFILLSURFACE invoke SelectObject,mDC,hOldBrush invoke DeleteObject,hBrush invoke SelectObject,mDC,hBitmap mov hReturn,eax invoke DeleteDC,mDC mov eax,hReturn ret SetBmpColor endp
First we declare some local variables needed for our procedure. First we create a compatible memory DC with CreateCompatibleDC. Next select the bitmap into the memory DC with SelectObject. The GetSysColor function retrieves the current color of the specified display element which returns RGB color we use CreateSolidbrush to create a logical brush of the specified color we've selected.Then select the brush to the device context. This function returns the previously selected object of the specified type. we store this to the a local variable. The GetPixel function retrieves the red, green, blue color value of the pixel at the specified coordinates. we use the our Device context and 1,1 the the first pixel of the image.The ExtFloodFill function an area of display surface with the brush we've selected.Then revert what we've done Select old brush delete the Device context we've created.
Short say, It is used to make some changes the image we've loaded ,without this procedure in the image loaded in the toolbar would be just like in the bitmap image. To remove the background image and to display our specific image only we need to use this procedure. Then we store the handle.
mov tbab.hInst, 0 push hTbBmp pop tbab.nID invoke SendMessage,hToolBar,TB_ADDBITMAP,12,ADDR tbab
We use our our own toolbar images so we set tbab.hInst as 0 and tbab.nID as handle to our bitmap image. And add bitmap to our toolbar by TB_ADDBITMAP image.
TBextraData TBblank TBbutton 0,50 TBbutton 1,51 TBbutton 2,52 TBbutton 3,53
We use our macro to set our buttons first button id and command id is passed as parameters for our macro.
.if uMsg==WM_SIZE invoke SendMessage,hToolBar,TB_AUTOSIZE,0,0
we allow our toolbar to be automatically resized by sending TB_AUTOSIZE message. Remaining things are same as above.
.elseif uMsg==WM_CLOSE invoke DeleteObject,hTbBmp invoke EndDialog,hWnd
The application must call the DeleteObject function to delete bitmap handle returned by the LoadBitmap function.
i've attached full source code of the example programs and included a extra program which is merged with previous tutorial and which forms a basic text editor which can save and view files with toolbar.
Attached File(s)
-
toolbar.zip (8.84K)
Number of downloads: 866
This post has been edited by Hooker: 27 October 2012 - 01:11 AM