News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

help :about bitmap button

Started by ezme, February 03, 2006, 06:32:38 AM

Previous topic - Next topic

ezme

sorry for my poor english, :( expect u can understand my meaning

i wan't to create a bitmap button in a program interface design,just like the MFC's CBitmapClass does
when mouse entering or leaving the client region,the botton use diffrent bitmap to draw the client region

from msdn manual :
define the buttom style OWNERDRAW, and in the windows message loop ,
by capture the msg WM_OWNERDRAW ,we can create a bitmap button
capture the message WM_NOTIFY ,we can know when the mouse entering or leaving the button's region

that's i know,could anyone help me? just give a example,thanks a lot ! :toothy

santa

source:

********************************************************

.data

hButton2 dd ?



szButton db 'BUTTON', 0

SetBitmap   PROTO :DWORD, :DWORD
hInstance   : DWORD


WndProc   Proc uses ebx esi edi hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

      mov eax, uMsg

   .IF eax==WM_CREATE


invoke   CreateWindowEx, 0, offset szButton, 0, WS_CHILD or BS_BITMAP or \
   BS_CENTER or WS_VISIBLE, 96, 15, BUTTON_WIDTH, BUTTON_HEIGH, hWnd, \
   0, hInstance, 0

mov   hButton2, eax
invoke   SetBitmap, eax, IDB_BMP

________________

SetBitmap   Proc, hButton:DWORD, IDBMP:DWORD
   invoke   LoadBitmap, hInstance, IDBMP
   invoke   SendMessage, hButton, BM_SETIMAGE, IMAGE_BITMAP, eax
   ret
SetBitmap   endp
________________

**********************************************************************************

*.rc file

#define IDB_BMP      300

IDB_BMP BITMAP LOADONCALL MOVEABLE DISCARDABLE Resource\bitmap.bmp


***********************************************************************************

:8)






zcoder

About 3 years ago I made such a example code
to skin a window and while I was at it I skined the buttons in it.

so if you look good in the example I provided you will see how to
use 3 images for a button, a regular image, mouse over image and a pushed image.

If you have problems extracking the button parts out of this example
Just let me know and I can do it for you and place it all into a simpler example.

infact, if you look at the BMPS I used for the images you will see they have no text
on them, so the functions I wrote in the buttonEX proc does that for you, even to
make the color change when mouse is over and to look ingraved when you push the button.

Zcoder....


[attachment deleted by admin]
Back in 1979, My computer ran so fine.
And there was no such thing,
As a Microsoft Crashed Machine.
http://zcoder.110mb.com
http://www.dietzel.com/partner/idevaffiliate.php?id=345_6  Free Domain Names

ezme

thanks very much,
reading code,see u later :toothy

ezme

zcoder's sample is a very good example for leaning windows gdi functions and message looping etc,
thanks very much.
but i'm puzzled with a function,it is SetWindowLong,the second parameter
i searched in MSDN ,but had no enough explanation for the second parameter
would u plz show us a list ,what the values of the second parameter stand for
thanks for your patient working :U

-----------------------------------------------------------------------------------

;*************************************************************************
; We just created a TRANSPARENT window, now it is a class, so now lets
; store the handles of our images (up image, down image, over image) into
; that all famouse extra window memory area for later use.
;*************************************************************************
             invoke SetWindowLong,hButnW,0,hImageUp
             invoke SetWindowLong,hButnW,4,hImageDwn
             invoke SetWindowLong,hButnW,12,hImageOvr
-----------------------------------------------------------------------------------
    .if uMsg == WM_LBUTTONDOWN
        invoke GetWindowLong,hWin,4
        mov hImageDwn, eax
        invoke GetWindowLong,hWin,8
        mov hImage, eax

        invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hImageDwn
-----------------------------------------------------------------------------------

ramguru

In this case this is an offset from 0 in that custom data will be written (4bytes), you can write there if you reserved some space (mov wc.cbWndExtra,     16). Sixteen bytes are reserved thefore you can access 0,4,8,12 offsets.. It's the only good way to retrieve data that supposed to remain unchanged, especially for custom control...

ramguru

The most efficient way to deal with bmp buttons is to store all three states (images) in one bmp, though ImageList.. is dedicated only for icons you can play cleverly and use it for your own reason, that's what I did... (Just e few extra code lines to "\m32lib\bmpbutn.asm")

[attachment deleted by admin]

zcoder

Ezme,
I will try to explain the SetWindowLong,hButnW,0,hImageUp
when you craete a class window, you have the choice to have
extra data bytes where you can store some data.

so the 0 in 2 param of SetWindowLong is the start of that area
and sence hImageUp is DWORD(4 bytes)  we store it at Extradata[0]
on the next SetWindowLong we store the handle hImageDwn at Extradata[4]
you see they go as 0 4 12 16 ect.
            invoke SetWindowLong,hButnW,0,hImageUp
            invoke SetWindowLong,hButnW,4,hImageDwn
            invoke SetWindowLong,hButnW,12,hImageOvr

Unless you are using them as WORD or BYTE storage's
infact this Extra data area is what is importand for custom controls you
would like to make and if it's not enough memory you could use
GlobalAlloc to allocate the amount you need then use the casted pointer
to store it in the extra data area.

But before you can use the extra data in a class make sure you
fill in the       wc.cbClsExtra ,  wc.cbWndExtra with 20 when you
Create the class.  I think that is the limit just 4 DWORDS as I have
not been able to go Higher then that.

I am not sure if that explains it enough but I tried lol

By the way, I see you are very good at noticing what code does
and what is important code. Keep up the good work we can use
more people like you.

Zcoder....
Back in 1979, My computer ran so fine.
And there was no such thing,
As a Microsoft Crashed Machine.
http://zcoder.110mb.com
http://www.dietzel.com/partner/idevaffiliate.php?id=345_6  Free Domain Names

zooba

Keep in mind that some of the standard controls use this space. The safest way of storing extra information with a control (unless you've specifically created the class) is to allocate it elsewhere and store a pointer in GWL_USERDATA (accessible through GetWindowLong and SetWindowLong). Again, you have to be careful if you're customising an already customised control that may use this feature.

Cheers,

Zooba :U

ezme

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Image Button lib wrote by Zcoder, 2003
; Developed by ezme, 2006 (ezme@21cn.com)
;
;   I develop Zcoder's code,add the gray status.
;   You have choice to use 1,2,3 or 4 status images,or draw some text on
; the button
;   If you want to disable it,get the handle of the button, send a message
; using SendMessage,hBmpBtnStart,WM_USER + 0,NULL,NULL, or disable
; SendMessage,hBmpBtnStart,WM_USER + 1,NULL,NULL
;
;   I have not make a full test with this code,maybe it has some mistake,
; tell me if u have any questions
;
;   Thanks to Zcoder,ramguru,zooba!
;
; USING examples
;invoke   ImageTextBtnEx,hWnd,602,3,14,14,\
;   BMPBTN_STD,IDC_CLOSE,NULL,\
;   IDB_X_NORMAL,IDB_X_CLICK,
;   IDB_X_MOUSEON,NULL\
;
;invoke   ImageTextBtnEx,hWnd,384,333,102,23,\
;   BMPTXTBTN_EX,IDC_START,\
;   addr szButtonStart,\
;   IDB_B_NORMAL,IDB_B_CLICK,\
;   IDB_B_MOUSEON,IDB_B_DISABLE
;invoke   ImageTextBtnEx,hWnd,502,333,102,23,\
;   BMPTXTBTN_STD,IDC_CANCEL,\
;   addr szButtonCancel,\
;   IDB_B_NORMAL,IDB_B_CLICK,\
;   IDB_B_MOUSEON,IDB_B_DISABLE
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;*******************************************************************
; Here, you can modify the font color for diff button status
;*******************************************************************
BTNFONT_UP_COLOR   equ   0FEFEFEH
BTNFONT_DOWN_COLOR   equ   0FEFEFEH
BTNFONT_OVER_COLOR   equ   0FEFEFEH
BTNFONT_GRAY_COLOR   equ   0FEFEFEH

BMPBTN_LOAD_FROM_FILE   equ   100000000B
BMPBTN_GRAYFLAG      equ   20
;*******************************************************************
; Some values have defined for normal used button status
;*******************************************************************
BMPBTN_TEXT   equ   00000001B
BMPBTN_UP   equ   00000010B
BMPBTN_DOWN   equ   00000100B
BMPBTN_OVER   equ   00001000B
BMPBTN_GRAY   equ   00010000B

BMPBTN_STD   equ   BMPBTN_UP or BMPBTN_DOWN or BMPBTN_OVER
BMPBTN_EX   equ   BMPBTN_UP or BMPBTN_DOWN or BMPBTN_OVER or BMPBTN_GRAY
BMPTXTBTN_STD   equ   BMPBTN_UP or BMPBTN_DOWN or BMPBTN_OVER or BMPBTN_TEXT
BMPTXTBTN_EX   equ   BMPBTN_UP or BMPBTN_DOWN or BMPBTN_OVER or BMPBTN_TEXT or BMPBTN_GRAY

      .data
BmpBtnSubWinClass   db   "STATIC",0      
BmpTxtBtnClass      db   "BmpButtonClass",0
stTME         TRACKMOUSEEVENT<>
BmpBtnClickFlag      dd   0
BmpBtnImageOver      dd   0
      .code

;*******************************************************************
; This procedure creates a image button class. a class where
; the button has a normal state, and when the mouse is hovering
; over it, it changes images, and when you click on it it changes
; to the third image, the click image, and also u can disable it :)
; You have a choice to draw some text or not.
;*******************************************************************
ImageTextBtnEx   proc   hWin:DWORD,Xpos:DWORD,Ypos:DWORD,Wwd:DWORD,Wht:DWORD,
         dwLoadFlg:DWORD,ID:DWORD,lpText:DWORD,
         Image1:DWORD,Image2:DWORD,Image3:DWORD,Image4:DWORD
      LOCAL   hImageUp    :DWORD
      LOCAL   hImageDwn   :DWORD
      LOCAL   hImageOvr   :DWORD
      LOCAL   hImageGry   :DWORD
      LOCAL   hImage      :DWORD
      LOCAL   hModule     :DWORD
      LOCAL   Wwidth      :DWORD
      LOCAL   Wheigth     :DWORD
      LOCAL   hButnW      :DWORD
      LOCAL   rect       :RECT
      LOCAL   hDC       :DWORD
      LOCAL   hMemDC      :DWORD
      LOCAL   hOldObject  :DWORD
      LOCAL   Xsize       :DWORD
      LOCAL   Ysize       :DWORD
      LOCAL   Tcount      :DWORD
      LOCAL   WRct       :RECT
      LOCAL   wc       :WNDCLASSEX
      LOCAL   tm       :TEXTMETRIC
;*********************************************************************
; First we start by getting the Module handle of our main program.
; this part is not needed, but if you place it in a library you will
; need this, or you can use the GetParent API call. Sence this was
; pulled right out from my library it is here.
;*********************************************************************
      invoke   GetModuleHandle,NULL
      mov   hModule, eax
;*********************************************************************
; One of the params sent to this procedure is the load flag, what this
; means is simple, if the flag is set it tells us to load the images
; from disk, which means that the params (Image1, Image2, Image3) are
; pointers to BITMAP NAMES and paths. if the flag is zero we load
; the images from resource. COOL hu??
;*********************************************************************
      .if   dwLoadFlg & BMPBTN_LOAD_FROM_FILE
         .if   dwLoadFlg & BMPBTN_UP
         invoke   LoadImage,hModule,Image1,IMAGE_BITMAP,Wwd,Wht,LR_LOADFROMFILE
         mov   hImageUp, eax
         .endif
         .if   dwLoadFlg & BMPBTN_DOWN
         invoke   LoadImage,hModule,Image2,IMAGE_BITMAP,Wwd,Wht,LR_LOADFROMFILE
         mov   hImageDwn, eax
         .endif
         .if   dwLoadFlg & BMPBTN_OVER
         invoke   LoadImage,hModule,Image3,IMAGE_BITMAP,Wwd,Wht,LR_LOADFROMFILE
         mov   hImageOvr, eax
         .endif
         .if   dwLoadFlg & BMPBTN_GRAY
         invoke   LoadImage,hModule,Image4,IMAGE_BITMAP,Wwd,Wht,LR_LOADFROMFILE
         mov   hImageGry, eax
         .endif
      .else
         .if   dwLoadFlg & BMPBTN_UP
         invoke   LoadImage,hModule,Image1,IMAGE_BITMAP,Wwd,Wht,0
         mov   hImageUp, eax
         .endif
         .if   dwLoadFlg & BMPBTN_DOWN
         invoke   LoadImage,hModule,Image2,IMAGE_BITMAP,Wwd,Wht,0
         mov   hImageDwn, eax
         .endif
         .if   dwLoadFlg & BMPBTN_OVER
         invoke   LoadImage,hModule,Image3,IMAGE_BITMAP,Wwd,Wht,0
         mov   hImageOvr, eax
         .endif
         .if   dwLoadFlg & BMPBTN_GRAY
         invoke   LoadImage,hModule,Image4,IMAGE_BITMAP,Wwd,Wht,0
         mov   hImageGry, eax
         .endif
      .endif
;*************************************************************************************
; At this point we have loaded the three images, these images are blank and now we
; need to draw text on the images. each image get the same text that was pass to us
; thru lpText. but each button has a small difference to them as far as the text goes.
; we start out by building a rect of the size sent to use with Wwd and Wht so the
; buttons will be the size we ask them to be, even if the actual images are larger
; or smaller.
;*************************************************************************************
      .if   (dwLoadFlg & BMPBTN_TEXT) && (lpText != NULL)
         mov   [rect.top],0
         mov   [rect.left],0
         mov   eax,[Wwd]
         mov   [rect.right],eax
         mov   [Xsize],eax
         mov   eax,[Wht]
         mov   [rect.bottom],eax
         mov   [Ysize],eax
         
         invoke   GetDC,hWin
         mov   [hDC],eax
   ;**********************************************************************
   ; We are now going to create the three images we will build the first
   ; image button by getting a DC to our main window and then Create a
   ; Compatible DC from the main window, then we select the up image into
   ; this hMemDC so we can draw on it. we do this for each image. one at
   ; a time.
   ;**********************************************************************
         invoke   CreateCompatibleDC,hDC
         mov   [hMemDC],eax
         invoke   GetStockObject,DEFAULT_GUI_FONT
         invoke   SelectObject,hMemDC,eax
   ;*********************************************************************
   ; now lets figure the size of the rect area where we will draw the
   ; text, the text must be centered, and aligned in the button so lets
   ; get the text average width and times it by the char count of
   ; the text line, then subtract this from the width of the button
   ; then divide this in half, to get the right amount to add to
   ; the left side of the rect so the text will be drawn in the
   ; center of the button.
   ;*********************************************************************
         invoke   lstrlen,lpText
         mov   [Tcount],eax
         invoke   GetTextMetrics,hMemDC,addr tm
         mov   eax,[tm.tmAveCharWidth]
         mov   ecx,[Tcount]
         xor   edx,edx
         mul   ecx
         mov   ecx,[Xsize]
         sub   ecx,eax
         mov   eax,ecx
         mov   ecx,2
         div   ecx
         add   [rect.left],eax
   ;*********************************************************************
   ; Get the text height and subtract this from the height of the button
   ; then divide this in half to get the right value to add to the top
   ; so the text is center Horz.
   ;*********************************************************************
         mov   eax,[tm.tmHeight]
         xor   edx,edx
         mov   ecx,[Ysize]
         sub   ecx,eax
         mov   eax,ecx
         mov   ecx,2
         div   ecx
         add   [rect.top],eax
         invoke   DeleteDC,hMemDC
   ;**********************************************************************
   ; Now that the text rect is made, we can use it to draw on each buttons
   ; face, so we draw the text in white, then increase the rect's top and
   ; left by one pixel and draw the text in black, this creates the
   ; illustion of imbosed text.
   ;**********************************************************************
         .if   dwLoadFlg & BMPBTN_UP
            invoke   CreateCompatibleDC,hDC
            mov   [hMemDC],eax
            invoke   SelectObject,hMemDC,hImageUp
            mov   [hOldObject],eax
            invoke   GetStockObject,DEFAULT_GUI_FONT
            invoke   SelectObject,hMemDC,eax
            invoke   SetBkMode,hMemDC,TRANSPARENT
            invoke   SetTextColor,hMemDC,BTNFONT_UP_COLOR
            invoke   DrawText,hMemDC,lpText,Tcount,addr rect,DT_LEFT
            invoke   DeleteObject,hOldObject
            invoke   DeleteDC,hMemDC
         .endif
   ;********************************************************************
   ; Now we create another button image in memory and do just the same
   ; as above, but with RED in place of black, this will be our mouse
   ; hover button. otherwise it's the same as above.
   ;********************************************************************
         .if   dwLoadFlg & BMPBTN_OVER
            invoke   CreateCompatibleDC,hDC
            mov   [hMemDC],eax
            invoke   SelectObject,hMemDC,hImageOvr
            mov   [hOldObject],eax
            invoke   GetStockObject,DEFAULT_GUI_FONT
            invoke   SelectObject,hMemDC,eax
            invoke   SetBkMode,hMemDC,TRANSPARENT
            invoke   SetTextColor,hMemDC,BTNFONT_OVER_COLOR
            invoke   DrawText,hMemDC,lpText,Tcount,addr rect,DT_LEFT
            invoke   DeleteObject,hOldObject
            invoke   DeleteDC,hMemDC
         .endif
   ;**********************************************************************
   ; Now we create another button image in memory and do just the same
   ; as the above two, but with black and white reversed,this button is
   ; simuler to the first button but the colors are reversed to create a
   ; sunkin text look. otherwise it's the same as above. this button
   ; will be our clicked button.
   ;**********************************************************************
         .if   dwLoadFlg & BMPBTN_DOWN
            invoke   CreateCompatibleDC,hDC
            mov   [hMemDC],eax
            invoke   SelectObject,hMemDC,hImageDwn
            mov   [hOldObject],eax
            invoke   GetStockObject,DEFAULT_GUI_FONT
            invoke   SelectObject,hMemDC,eax
            invoke   SetBkMode,hMemDC,TRANSPARENT
            invoke   SetTextColor,hMemDC,BTNFONT_DOWN_COLOR
            invoke   DrawText,hMemDC,lpText,Tcount,addr rect,DT_LEFT
            invoke   DeleteObject,hOldObject
            invoke   DeleteDC,hMemDC
         .endif
   ;**********************************************************************
   ; Now we create another button image in memory for disable
   ;**********************************************************************
         .if   dwLoadFlg & BMPBTN_GRAY
            invoke   CreateCompatibleDC,hDC
            mov   [hMemDC],eax
            invoke   SelectObject,hMemDC,hImageGry
            mov   [hOldObject],eax
            invoke   GetStockObject,DEFAULT_GUI_FONT
            invoke   SelectObject,hMemDC,eax
            invoke   SetBkMode,hMemDC,TRANSPARENT
            invoke   SetTextColor,hMemDC,BTNFONT_GRAY_COLOR
            invoke   DrawText,hMemDC,lpText,Tcount,addr rect,DT_LEFT
            invoke   DeleteObject,hOldObject
            invoke   DeleteDC,hMemDC
         .endif
         invoke   ReleaseDC,hWin,hDC
      .endif
;**************************************************************************      
; Now that we created our three button images now we can create our
; TRANSPARENT window class to set our buttons in. classing is easy
; as pie, yes I said class, and the class goes something like this.
;**************************************************************************
      mov   wc.cbSize,sizeof WNDCLASSEX
      mov   wc.style,CS_BYTEALIGNWINDOW
      mov   wc.lpfnWndProc,offset ImageTextBtnProcs
      mov   wc.cbClsExtra,NULL
      mov   wc.cbWndExtra,28
      push   hModule
      pop   wc.hInstance
      mov   wc.hbrBackground,COLOR_BTNFACE+1
      mov   wc.lpszMenuName,NULL
      mov   wc.lpszClassName,offset BmpTxtBtnClass
      mov   wc.hIcon,NULL
      invoke   LoadCursor,NULL,IDC_ARROW
      mov   wc.hCursor,eax
      mov   wc.hIconSm,NULL

      invoke   RegisterClassEx,ADDR wc

      invoke   CreateWindowEx,WS_EX_TRANSPARENT,
            addr BmpTxtBtnClass,NULL,
            WS_CHILD or WS_VISIBLE,
            Xpos,Ypos,100,100,hWin,ID,
            hModule,NULL

      mov   hButnW, eax
;*************************************************************************
; We just created a TRANSPARENT window, now it is a class, so now lets
; store the handles of our images (up image, down image, over image) into
; that all famouse extra window memory area for later use.
;*************************************************************************
      .if   dwLoadFlg & BMPBTN_UP
         invoke   SetWindowLong,hButnW,0,hImageUp
      .endif
      .if   dwLoadFlg & BMPBTN_DOWN
         invoke   SetWindowLong,hButnW,4,hImageDwn
      .endif
      .if   dwLoadFlg & BMPBTN_OVER
         invoke   SetWindowLong,hButnW,12,hImageOvr
      .endif
      .if   dwLoadFlg & BMPBTN_GRAY
         invoke   SetWindowLong,hButnW,16,hImageGry
      .endif
;*************************************************************************
; now lets create a STATIC window inside our new window class and set it
; to the main window class we just created. and set the "up image" into the
; static window.
;*************************************************************************
      invoke   CreateWindowEx,0,addr BmpBtnSubWinClass,NULL,
            WS_CHILD or WS_VISIBLE or SS_BITMAP,
            0,0,0,0,hButnW,ID,
            hModule,NULL
      mov   hImage, eax
      .if   dwLoadFlg & BMPBTN_UP
         invoke   SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hImageUp
         invoke   SetWindowLong,hButnW,BMPBTN_GRAYFLAG,FALSE
      .else
         invoke   SetWindowLong,hButnW,BMPBTN_GRAYFLAG,FALSE
      .endif
      invoke   SetWindowLong,hButnW,8,hImage
;*****************************************************************************
; Now notice that when we created the STATIC window we gave it not size, so
; now we will use a trick I learned to make it snap to the size of our images
; my getting the size of the STATIC window and setting the outer window to
; the STATIC windows size, this works because the STATIC window with the
; SS_BITMAP value will always snap to the size of the image set inside it so
; we can get this size and resize our outer class window to it.
;*****************************************************************************
      invoke   GetWindowRect,hImage,addr WRct
      mov   eax,WRct.bottom
      mov   edx,WRct.top
      sub   eax,edx
      mov   Wheigth,eax
      mov   eax,WRct.right
      mov   edx,WRct.left
      sub   eax,edx
      mov   Wwidth,eax
      invoke   SetWindowPos,hButnW,HWND_TOP,0,0,Wwidth,Wheigth,SWP_NOMOVE
;********************************************************************************
; Now we just show the window and we are done. and everyone is impressed at our
; buttons.
;********************************************************************************
      invoke   ShowWindow,hButnW,SW_SHOW
      mov   eax, hButnW
      ret
ImageTextBtnEx endp
;**********************************************************************************
;
;**********************************************************************************
ImageTextBtnProcs proc hWin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

      LOCAL   hImageUp    :DWORD
      LOCAL   hImageDwn   :DWORD
      LOCAL   hImageOvr   :DWORD
      LOCAL   hImageGry   :DWORD
      LOCAL   hImage      :DWORD
      LOCAL   hParent     :DWORD
      LOCAL   ID       :DWORD
      LOCAL   ptX       :DWORD
      LOCAL   ptY       :DWORD
      LOCAL   bWid       :DWORD
      LOCAL   bHgt       :DWORD
      LOCAL   Rct       :RECT

   .if   uMsg == WM_USER
      invoke   SetWindowLong,hWin,BMPBTN_GRAYFLAG,FALSE
      invoke   GetWindowLong,hWin,8
      mov   hImage, eax
      invoke   GetWindowLong,hWin,0
      mov   hImageUp, eax
      invoke   SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hImageUp
   .elseif   uMsg == WM_USER + 1
      invoke   SetWindowLong,hWin,BMPBTN_GRAYFLAG,TRUE
      invoke   GetWindowLong,hWin,8
      mov   hImage, eax
      invoke   GetWindowLong,hWin,16
      mov   hImageGry, eax
      invoke   SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hImageGry
   .endif
   invoke   GetWindowLong,hWin,BMPBTN_GRAYFLAG
   .if   eax == FALSE
      .if uMsg == WM_LBUTTONDOWN
         invoke   GetWindowLong,hWin,4
         mov   hImageDwn, eax
         invoke   GetWindowLong,hWin,8
         mov   hImage, eax

         invoke   SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hImageDwn
         invoke   SetCapture,hWin
         mov   BmpBtnClickFlag, 1
      .elseif uMsg == WM_MOUSEMOVE
         mov   eax,sizeof stTME
         mov   stTME.cbSize,eax
         mov   eax,TME_LEAVE
         mov   stTME.dwFlags,eax
         mov   eax,hWin
         mov   stTME.hwndTrack,eax

         invoke   TrackMouseEvent,addr stTME
         invoke   GetWindowLong,hWin,12
         mov   hImageOvr, eax
         .if   eax != 0
            invoke   GetWindowLong,hWin,8
            mov   hImage, eax
            .if   BmpBtnImageOver == 0
            invoke   SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hImageOvr
            mov   BmpBtnImageOver,1
            .endif
         .endif
      .elseif uMsg == WM_MOUSELEAVE
         invoke GetWindowLong,hWin,0
         mov hImageUp, eax
         invoke GetWindowLong,hWin,8
         mov hImage, eax
         invoke SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hImageUp
         mov BmpBtnImageOver,0
      .elseif uMsg == WM_LBUTTONUP
         .if   BmpBtnClickFlag == 0
            ret
         .else
            mov BmpBtnClickFlag, 0
         .endif

         invoke   GetWindowLong,hWin,0
         mov   hImageUp, eax
         invoke   GetWindowLong,hWin,8
         mov   hImage, eax
         invoke   SendMessage,hImage,STM_SETIMAGE,IMAGE_BITMAP,hImageUp
         mov   BmpBtnImageOver,0
         mov   eax, lParam
         cwde
         mov   ptX, eax
         mov   eax, lParam
         rol   eax, 16
         cwde
         mov   ptY, eax

         invoke   GetWindowRect,hWin,addr Rct

         mov   eax, Rct.right
         mov   edx, Rct.left
         sub   eax, edx
         mov   bWid, eax

         mov   eax, Rct.bottom
         mov   edx, Rct.top
         sub   eax, edx
         mov   bHgt, eax

         cmp   ptX, 0
         jle   @F
         cmp   ptY, 0
         jle   @F
         mov   eax, bWid
         cmp   ptX, eax
         jge   @F
         mov   eax, bHgt
         cmp   ptY, eax
         jge   @F

         invoke   GetParent,hWin
         mov   hParent, eax
         invoke   GetDlgCtrlID,hWin
         mov   ID, eax
         invoke   SendMessage,hParent,WM_COMMAND,ID,hWin
@@:
         invoke   ReleaseCapture

      .endif
   .endif
   invoke DefWindowProc,hWin,uMsg,wParam,lParam
   ret

ImageTextBtnProcs endp

zcoder

Good work, that is a good idea to have a diabled state.
I wonder why I forgot that state?? :( LOL

Anyway that is good, I will be adding that to my LIB
file and replace the old one.

Zcoder....
Back in 1979, My computer ran so fine.
And there was no such thing,
As a Microsoft Crashed Machine.
http://zcoder.110mb.com
http://www.dietzel.com/partner/idevaffiliate.php?id=345_6  Free Domain Names