Page 1 of 1

MASM-Toolbar control

#1 Hooker  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 5
  • View blog
  • Posts: 29
  • Joined: 17-August 12

Post icon  Posted 24 October 2012 - 03:21 AM

MASM Toolbar controls
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)


This post has been edited by Hooker: 27 October 2012 - 01:11 AM


Is This A Good Question/Topic? 0
  • +

Page 1 of 1