Click to See Complete Forum and Search --> : Mouseover event
Dimension
April 6th, 2004, 11:23 PM
Env: Win32 (Visual C++)
How can I implement the Mouseover event ? Assuming I have two bitmap buttons (IDC_Btn1, IDC_Btn2) in main dialog.
When Mouseover, IDC_Btn1 will change to IDC_Btn2. When Click, only the child Dialog will be displayed, and the button remains IDC_Btn2.
Any sample code, will be great. Thanks.
KVR1
April 7th, 2004, 03:36 AM
It is possible using TrackMouseEvent Function !
Refer MSDN or this Site for getting more details !
Dimension
April 9th, 2004, 02:24 AM
if have sample project code, it will be great.
Andreas Masur
April 9th, 2004, 04:27 AM
[Moved thread]
Erik Wiggins
April 9th, 2004, 07:54 AM
declare this globally
TRACKMOUSEEVENT tme;
put this in WinMain
tme.cbSize=sizeof(tme);
tme.dwFlags=TME_HOVER;
tme.hwndTrack=hWnd;]//hanlde of window you want the mouse over message for.
tme.dwHoverTime=HOVER_DEFAULT;
TrackMouseEvent(&tme)
put this in the Window Proceedure for the window
case WM_MOUSEHOVER:
//Process Mouse Over message here.
Dimension
April 9th, 2004, 10:04 AM
Thanks for the code.
How can I process the bitmap button changes ? in
case WM_MOUSEHOVER: ?
Dimension
April 14th, 2004, 05:54 AM
I would like process mouseover event for each button in my main Dialog. Not sure if your approach will work in my case.
Why I got TrackMouseEvent : undeclared identifier ?
RussG1
April 14th, 2004, 02:57 PM
I really haven't worked with TrackMouseEvent as of yet, but I think you should still be able to do what you want using it.
Set the HWND in your TRACKMOUSEEVENT structure to be that of the dialog.
In your WM_MOUSEHOVER handler, use GetCursorPos and ChildWindowFromPoint to do hit testing, and compare the HWND value returned with the HWND's for your buttons to see if the cursor is over a button. If it is over a button then use SetWindowLong with GWL_ID to change the Control ID of your button, etc.
TrackMouseEvent is defined for Windows 98 and later, so you may have to define _WIN32_WINDOWS=0x0410 to use it (may be why you are getting undeclared identifier message).
RussG1
April 14th, 2004, 06:07 PM
BTW:
I am not exactly sure what it is you are trying to do, as changing the Control ID for a button when the mouse hovers over it seems a bit strange (are you doing this only once? should the button revert back to the original id at some point? etc.) Also, I am not sure if you want to catch the message when the mouse moves over the button or just when it hovers over the button. If you want to do it when the mouse moves over the button then you would probably do it differently. You would probably need to subclass the button and handle the WM_MOUSEMOVE message in the button's window procedure. Again, I cannot be specific as I do not completly understand what it is you want to do, but you can check out ownerdrawn button examples for flat buttons, etc, to see how it is handled. Basically you would handle the WM_MOUSEMOVE message so that you know when the mouse moves over the button (check which mouse buttons are pressed, if any, etc), and under the appropriate conditions use TrackMouseEvent (within the handler for WM_MOUSEMOVE), with TME_LEAVE for dwFlags paramater in the TRACKMOUSEEVENT structure, so that you are sent the WM_MOUSELEAVE message when the mouse leaves the button's area, etc (and handle that message). This way you know when the mouse enters the buttons area, and when it leaves (you would probably want to use global boolean variables as flags to keep track of things, so you can test for certain conditions and only handle the WM_MOUSEMOVE message under the those conditions, and clear those flags in the WM_MOUSELEAVE message, etc). The specifics would depend on the specifics of what you want to do.
Dimension
April 14th, 2004, 08:31 PM
ok...very simple. what I to do is to swap between two bitmap button when mouseover the button. That's all.
I think there is not necessary to change any Control ID, etc.
Dimension
April 14th, 2004, 08:32 PM
when Mouse leaves the button, it will back to original bitmap button.
RussG1
April 14th, 2004, 09:10 PM
ahh OK, your original post made it sound like you wanted to change control id's.
Originally posted by Dimension
When Mouseover, IDC_Btn1 will change to IDC_Btn2.
Also "swap between two bitmap button" sounds like you want to swap buttons.
Originally posted by Dimension
what I to do is to swap between two bitmap button when mouseover the button
Probably just an language issue, not a big deal (just confusing).
So what you want is a normal button that changes pictures when the mouse is over it.
In that case, I assume you have at at least 2 bitmaps, one for the MouseOver state and one for the normal state.
You should probably use a global boolean variable, i.e. bIsHighlighted to track which image the button currently has, initially set to false.
In your subclassed buttons window proc, handle the WM_MOUSEMOVE message. In the WM_MOUSEMOVE handler, check to see if bIsHighlighted is TRUE and if it is, return the default window proc, etc. If it is false, set it to true, and send the BM_SETIMAGE message to change the buttons bitmap to the MouseOver version. Use TrackMouseEvent (with TME_LEAVE) so that it sends the WM_MOUSELEAVE message when the mouse leaves the buttons area.
Handle the WM_MOUSELEAVE message, and in tht handler, set bIsHighlighted to false, and send the BM_SETIMAGE message to set the buttons image back to normal state, etc.
Are you doing this for multiple buttons, or just one button?
It is not that difficult, if I have the chance I will see if I can provide an example for you, if you cannot figure out how to do it yourself.
BTW:
To use WM_MOUSEMOVE and WM_MOUSELEAVE and TRACKMOUSEEVENT you need to define _WIN32_WINNT as 0x0400 and WINVER as 0x0500 (or higher).
RussG1
April 14th, 2004, 11:49 PM
Here is an example, for two buttons (both buttons have the BS_BITMAP style and use the same bitmaps).
// IDC_DLGBTN1 is a button resource
// IDC_DLGBTN2 is a button resource
// IDB_BMP_NORMAL is a bitmap resource
// IDB_BMP_HILIGHT is a bitmap resource
// in WM_INITDIALOG of main dialog procedure
hWndBtn1 = GetDlgItem(hWnd, IDC_DLGBTN1);
hWndBtn2 = GetDlgItem(hWnd, IDC_DLGBTN2);
// load bitmaps
hBmpNormal = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BMP_NORMAL));
hBmpHiLight = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BMP_HILIGHT));
// set initial button images
SendMessage(hWndBtn1, BM_SETIMAGE,
(WPARAM)IMAGE_BITMAP, (LPARAM)hBmpNormal );
SendMessage(hWndBtn2, BM_SETIMAGE,
(WPARAM)IMAGE_BITMAP, (LPARAM)hBmpNormal);
// subclass buttons
wpOrigButtonProc = (WNDPROC) SetWindowLong(hWndBtn1,
GWLP_WNDPROC, (LONG) NewButtonProc);
/* same original btn proc */ SetWindowLong(hWndBtn2,
GWLP_WNDPROC, (LONG) NewButtonProc);
// in WM_CLOSE of main dialog procedure
SetWindowLong(hWndBtn1, GWLP_WNDPROC, (LONG)wpOrigButtonProc);
SetWindowLong(hWndBtn2, GWLP_WNDPROC, (LONG)wpOrigButtonProc);
If you want to use different bitmap images for the different buttons, then you could compare the HWND value to determine which button the mouse is over (or is leaving), and set the correct bitmap for that button, etc.
This is just the basic stuff. You may wanna check which mouse button is pressed in your WM_MOUSEMOVE procedure and do something different dependiing on which button is pressed, etc.
Dimension
April 15th, 2004, 01:36 AM
Where should I define _WIN32_WINNT as 0x0400 and WINVER as 0x0500 (or higher) ?
Dimension
April 15th, 2004, 01:58 AM
I defined this
_WIN32_WINNT as 0x0400 and WINVER as 0x0500
in StdAfx.h. It works ok.
I got this error C2065: 'GWLP_WNDPROC' : undeclared identifier.
Why ?
Dimension
April 15th, 2004, 02:08 AM
anyway, I put below in .h file (not sure it's correct or not)
After compilation, I still can't get mouseover works after integrate your code in.
RussG1,
to answer your question, I'm doing this for multiple buttons. each button will have highlight state and normal state ( each button will have two bitmap - highlight bitmap and normal bitmap)
Can you post a sample project file with your code below ?
Regards.
Dimension
April 15th, 2004, 02:27 AM
anyway, I put below in .h file (not sure it's correct or not)
After compilation, I still can't get mouseover works after integrate your code in.
RussG1,
to answer your question, I'm doing this for multiple buttons. each button will have highlight state and normal state ( each button will have two bitmap - highlight bitmap and normal bitmap)
Can you post a sample project file with your code below ?
Regards.
RussG1
April 15th, 2004, 02:31 AM
Put the defines in the .h file at the top, before you include windows.h like this.
#define _WIN32_WINNT 0x0400
#define WINVER 0x0500
#define WIN32_LEAN_AND_MEAN
#define STRICT
#include <windows.h>
#include "resource.h"
, etc.
As for GWLP_WNDPROC, I apologize, that should be GWL_WNDPROC. GWLP_WNDPROC is used with SetWindowLongPtr (although GWLP_WNDPROC should work, as it has same definition (and it worked when I tried it). I am not sure why it is not defined for you, maybe you do not have latest Platform SDK?).
As for a sample, I just added that code to the sample I attached previously and it worked. Give me a sec and I will attach the modifed example (I was testing some other things in that sample, so I need to clean out the extra stuff...).
*edit *
putting the defines for the windows version, etc. in stdafx.h is fine as well (I missed that part of your post)
RussG1
April 15th, 2004, 02:48 AM
OK, here is the modified sample.
The bitmaps are nothing fancy, I just used the bitmap editor is VS to create basic bitmaps for example, everything else should be same as it was previously.
Let me know if you have any problems with it.
** edit ***
Modified sample per request below.
Dimension
April 15th, 2004, 03:35 AM
Instead of loading bitmap, if I create picture in the Main Dialog with IDC_Normal, IDC_Normal will point to/use IDB_BMP_NORMAL ? how can I use IDC, instead of IDB.
Same for IDB_BMP_HIGHLIGHT, I also use IDC_Highlight
RussG1
April 15th, 2004, 04:14 AM
The resource name is just a name, it can be whatever you want (IDB_NORMAL, IDC_NORMAL, XXX_NORMAL, XXX_XXXXX, XXXXXX etc, whatever you want).
What do you mean by "create picture in the Main Dialog" as opposed to loading the bitmap from a resource?
How are you creating the picture?
***edit***
Open up resource.h and sample.rc in a text editor and you will see how the bitmaps are defined and the filenames that they point to. You can change the resource names for the bitmaps to whatever you want, just make sure that they match in the .rc file, the resource.h file, and in the LoadBitmap function (or whatever method you are using to load your bitmaps).
Dimension
April 15th, 2004, 04:29 AM
I understand what U mean.
What I meant is in the Dialog,
I insert a picture, set the ID to be ...let say IDC_NORMAL, under picture properties it use Type BITMAP, Image IDB_BMP_NORMAL
then I Insert another picture into the Dialog, set the ID to be IDC_HIGHLIGHT, under picture properties, it use Type Bitmap, Image IDB_BMP_HIGHLIGHT
So, now I have IDC_NORMAL and IDC_HIGHLIGHT instead of using LoadBitmap IDB_BMP_NORMAL and IDB_BMP_HIGHLIGHT.
RussG1
April 15th, 2004, 04:38 AM
I am not sure I understand completely.
Do you mean you insert a Picture Control into the dialog (a picture control is nothing more than a static control that displays a picture (when set to type bitmap)). It is not the picture itself, thus cannot be used as an image for a button. You would have to get the handle of the bitmap that is displayed by the picture control and then use that handle in your BM_SETIMAGE message to use that bitmap on your button. (a picture control is meant to show a picture, and not to be used as an imagelist, etc, if you are not using it to show a picture on the dialog, you are better off just doing as I did, and insert a bitmap resouce into the project rather than using a picture control).
RussG1
April 15th, 2004, 04:43 AM
BTW: If there is some reason why you need to use the picture control this way, you can send the STM_GETIMAGE message to the Picture Control, to retrieve the handle of the bitmap, and then you should be able to use that handle (store it in a global HBITMAP variable) in your BM_SETIMAGE message.
Dimension
April 15th, 2004, 04:48 AM
okie..I use bitmap instead. I tried and the method is ok. But the problem is the bitmap can not display properly.
Note: all my bitmap contains more than 256 colors. it cannot load in the bitmap editor.
How can I fix that ?
Dimension
April 15th, 2004, 05:02 AM
ok, if I use STM_GETIMAGE, what are the changes in your sample project ? I'm trying with no luck.
Maybe can you create two picture controls (IDC_NORMAL) and (IDC_HIGHLIGHT) and resend me the sample? Thanks a lot.
RussG1
April 15th, 2004, 05:04 AM
I am not sure why the VS editor will not let you edit some bitmaps, as you can create True Color bitmaps, in the editor by clicking the "Colors" listbox and changing it to True Color. I am not sure of any fix for this, but you can still use the bitmaps, you just cannot edit them in the VS editor (at least I don;t know of any way to do it)
As for your bitmaps not displaying properly, I am not sure, but you may want to use LoadImage rather than LoadBitmap, as LoadBitmap creates a new bitmap that is compatible with the display (thus the bitmap may be modified).
RussG1
April 15th, 2004, 05:15 AM
To modfiy the code to use STM_GETIMAGE, you need only change the following.
Remove or comment out the LoadBitmap lines in WM_INITDIALOG and replace with the following:
// get HWND's for the picture controls
HWND hWndStatic1 = GetDlgItem(hMain, IDC_STATIC1);
HWND hWndStatic2 = GetDlgItem(hMain, IDC_STATIC2);
// get handle to bitmaps from picture controls
hBmpNormal = (HBITMAP)SendMessage(hWndStatic1,
STM_GETIMAGE, IMAGE_BITMAP, 0);
hBmpHiLight = (HBITMAP)SendMessage(hWndStatic2,
STM_GETIMAGE, IMAGE_BITMAP, 0);
The rest of the code should be the same.
Dimension
April 15th, 2004, 05:41 AM
RussG1, I tried your STM_GETIMAGE with no success. The bitmap picture can not be loaded properly. The mouseover action seems ok.
Dimension
April 15th, 2004, 05:45 AM
Whenever I mouseover, it will change to Grey color, instead of display my picture control bitmap.
RussG1
April 15th, 2004, 05:51 AM
Hmm... To be sure we are talking about the same thing...
You have 2 Picture Controls on your main dialog?
The Picture Controls are set to tyoe Bitmap, and the Image property is set to a bitmap resource? (You can see the image in the Picture Control on the dialog in the dialog editor?)
In my example code, the resource ID's for the Picture Controls, are IDC_STATIC1 and IDC_STATIC2, you would change your code (where you get the HWND for the picture control) to use the resource ID's you assigned for the picture control (I assume they are IDC_NORMAL and IDC_HIGHLIGHT).
Make sure you do not comment out or remove any of the original code (except for the LoadBitmap lines). You still need to send the BM_SETIMAGE message to the buttons in WM_INITDIALOG, to set the initial image property for your buttons. This should be done after you use STM_GETIMAGE to get the handle of the bitmaps from the picture control's. (again the code should be exactly the same as it was previously except you replace the LoadBitmap lines with the above code, the rest of the code should not change and should be in the same order, etc).
RussG1
April 15th, 2004, 06:01 AM
I modified the previous sample to use Picture Controls, and STM_GETIMAGE as you requested and re-attached it. (scroll up and you will see that it is now sample4.zip).
RussG1
April 15th, 2004, 03:55 PM
I tried modifing my bitmaps so that they are true color bitmaps using gradient colors with a actual unique color count of approx. 461 colors. I tried using LoadBitmap, and using Picture Controls, and had no problems using either method. The pictures displayed properly in both cases, so I am not sure why you might be having a problem with your bitmaps. One possibility might be the size of your pictures. BM_SETIMAGE, centers the bitmap on the button by default, and if the image is to large to fit within the button, it is clipped on either side. As for the picture being grey, I would assume that either the button is disabled, or the bitmap handle is invalid (the picture control may not have a bitmap set, or the STM_GETIMAGE message was sent to wrong window (maybe the HWND is invalid, check the lines that get the HWND for the Picture Control's and verify that the correct Resource ID's of the Picture Control's are used (case sensative), and that the correct HWND for the parent dialog is used, also make sure that that the variable that you are using to store the bitmap handles is global, otherwise it will go out of scope when WM_INITDIALOG returns, and thus the handle will be invalid when it is used in WM_MOUSEMOVE)
Dimension
April 15th, 2004, 08:53 PM
I set the button (in your case is IDC_DLGBTN1 and IDC_DLGBTN2) to be "Owners Draw" and "Bitmap". "Owners Draw" is the one who make the grey area that I mentioned.
I want the button to be owners draw, so that I don't need to see the button shape there.
Dimension
April 15th, 2004, 09:16 PM
In your sample, when click IDC_DLGBTN1, child dialog will open, and if move the mouse away, it will back to IDC_NORMAL. How to make it stay at IDC_HIGHLIGHT eventhough the mouse is move away, since that the child dialog is still open.
and when close that child dialog, it will back to IDC_NORMAL.
Thanks.
another thing (with regard to my previous post), I only want to see the swapping between IDC_NORMAL and IDC_HIGHLIGHT without the button being visible. The BUtton should be OWNER DRAW and BITMAP.
RussG1
April 15th, 2004, 10:42 PM
Originally posted by Dimension
I set the button (in your case is IDC_DLGBTN1 and IDC_DLGBTN2) to be "Owners Draw" and "Bitmap". "Owners Draw" is the one who make the grey area that I mentioned.
I want the button to be owners draw, so that I don't need to see the button shape there.
Owner drawn means that you have to draw the button yourself.
You would need to handle the WM_DRAWITEM message and actually draw the button yourself. There are plenty of example out there for owner drawn buttons that you can refer too (look on the Codeguru and CodeProject sites).
RussG1
April 15th, 2004, 10:47 PM
Originally posted by Dimension
In your sample, when click IDC_DLGBTN1, child dialog will open, and if move the mouse away, it will back to IDC_NORMAL. How to make it stay at IDC_HIGHLIGHT eventhough the mouse is move away, since that the child dialog is still open.
and when close that child dialog, it will back to IDC_NORMAL.
Thanks.
Ok, this is completely different. To do this, you would probably check to see if the child dialog is visible in WM_MOUSEMOVE and WM_MOUSELEAVE, and only change the bitmap if the dialog is not visible. Then in the "OK" button handler for the child dialog, set the bitmap back to the normal one.
RussG1
April 15th, 2004, 10:52 PM
BTW: If you do not want the 3D button look, why not just use flat buttons?
Dimension
April 16th, 2004, 01:38 AM
OK. if I don't want to involve the button, and I would just place IDC_NORMAL and IDC_HIGHLIGHT as visible in Same Position. then the mouseover only dealing with IDC_NORMAL and IDC_HIGHLIGHT with SW_SHOW and SW_HIDE. Is that possible ?
RussG1
April 16th, 2004, 02:26 AM
When you hide the window, I would assume the would trigger a WM_MOUSELEAVE message which might cause problems with that scanario, you could however just use the picture controls, instead of the buttons as you want, and change the picture in the picture controls when the mouse is over it, etc (instead of hiding and showing, just change the bitmap same way that was done with the button).
Dimension
April 16th, 2004, 03:45 AM
RussG1, it would be nice if you re-post the sample project with this approach. Sorry to trouble you.
Example will make thing easier.. Many thanks.
RussG1
April 16th, 2004, 05:42 AM
Allright, I made all the changes that I think you want:
Removed buttons and replaced them with Picture Controls.
(note that I added the "Notify" style to the Picture Controls so that we can receive the WM_MOUSEMOVE/WM_MOUSELEAVE messages for the control).
Changed button subclassing code to subclass the picture control's instead.
Enabled mouseover action for the picture controls (bitmap changes when mouse is over the picture control).
Modified MouseOver and OnClick handlers for the Picture Controls so that if the child dialog is visible the picture does not go back to it's normal state until the child dialog is hidden (in the OnOk handler for the child dialog), etc.
The sample is attached as before and is now sample5.zip.
Hopefully this is what you are looking for.
Dimension
April 18th, 2004, 11:52 PM
Thanks RussG1. It works fine for me. Thanks.
One more question, How can I put a tooltips on those picture control (e.g IDC_STATIC1) ?
RussG1
April 19th, 2004, 02:37 AM
Baiscally you create a Tooltip Control window and add tools for each picture control. You add the TME_HOVER flag to the TRACKMOUSEEVENT structure so that we are sent WM_MOUSEHOVER messages in addition to the WM_MOUSELEAVE message. You would need to keep track of when the tip is visible, using a global boolean variable.
In WM_MOUSEHOVER, set boolean variable to TRUE, and send a message to the tooltip control to tell it to show the tooltip associtaed with that window.
In WM_MOUSELEAVE, check the value of the boolean var, if it is true, set it to false, and send a message to the tooltip control to tell it to hide the tip, etc.
This is a bit harder to explain so I just modified the example (now sample6.zip) and added tooltips.
The tooltip is shown when the mouse hovers over either of the picture control's (and hidden when the mouse leaves the pic controls window). I used a callback to set the tooltip text for each picture control. You can modify the text in the TTN_GETDISPINFO handler (in the WM_NOTIFY handler) of the picture control's window procedure.
Dimension
April 20th, 2004, 01:04 PM
Cool. Thanks.
I have One last question.
If I can change cursor to Hand Cursor, when mouseover, how can I achieve that ?
Assuming I have hand icon (IDI_HAND) under my resource.
RussG1
April 20th, 2004, 03:07 PM
Use LoadCursor to load the Hand Cursor (in WM_INITDIALOG, and store in global HCURSOR variable):
i.e.
hHandCursor = LoadCursor(NULL, IDC_HAND);
Use SetCursor in the WM_MOUSEMOVE handler to change the cursor to the hand cursor.
i.e.
SetCursor(hHandCursor);
Dimension
April 22nd, 2004, 02:55 AM
Thanks for the hand cursor.
Regarding the Mouseover, I notice one thing.
If I minimize my application, the bmpHilight will change back to bmpNormal, while the Dialog is still open.
I open my application, click on one bitmap button, to open a dialog, the mouse over procedure is fine. So, now the bitmap button is in Highlighted state. Then I minimized my application, then maximize again. I will see the bitmap button is in Normal State, and the dialog is still opened.
Are you aware of this ? Any reason why ?
RussG1
April 22nd, 2004, 07:32 AM
No, I have not seen that. I tested for that with the sample app, and the bitmap did not change upon minimize/restore.
I am not sure what would be causing that. Do you have any resizing code that may be affecting the handle of the bitmap? Make sure all your case statements are seperated with break statements (or returns), so that one case statement does not fall through to another (unless it is intended to be that way), etc. Try setting breakpoints on any lines that change the bitmap back to normal, and see if one of them fires after minimize/restore. Try adding a watch in the debugger on the handle for the bitmap and see if the value changes after you minimize/restore.
Without being able to see your code, it is hard to say what might be causing it, but I think you should be able to track down the problem using the debugger, etc.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.