View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001675 | JEDI VCL | 00 JVCL Components | public | 2004-04-20 16:23 | 2004-06-25 05:05 |
Reporter | glchapman | Assigned To | user72 | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | resolved | Resolution | fixed | ||
Product Version | |||||
Target Version | Fixed in Version | ||||
Summary | 0001675: Add support for flat menubars to TJvXPMenuItemPainter | ||||
Description | Starting with Windows XP, menubars now have a different default background color if SPI_GETFLATMENU is true. The attached patch slightly modifies TJvXPMenuItemPainter so that it uses this background color when owner-drawing (if appropriate). | ||||
Tags | No tags attached. | ||||
2004-04-20 16:23
|
JvMenus.pas.diff (2,239 bytes)
*** JvMenus.pas.orig Mon Mar 29 15:47:22 2004 --- JvMenus.pas Tue Apr 20 16:27:58 2004 *************** *** 660,665 **** --- 660,666 ---- // other usage fields FSelRect: TRect; FCheckedPoint: TPoint; + FFlatMenubar: boolean; procedure DrawBitmapShadow(X, Y: integer; B: TBitmap); procedure DrawImageBackground(ARect: TRect); override; *************** *** 2766,2771 **** --- 2767,2773 ---- end; procedure TJvXPMenuItemPainter.DrawItemBackground(ARect: TRect); + const COLOR_MENUBAR = 30; begin with Canvas do begin *************** *** 2783,2797 **** begin Brush.Assign(SelectionFrameBrush); Pen.Assign(SelectionFramePen); end else ! begin ! Brush.Color := clBtnFace; ! Brush.Style := bsSolid; ! Pen.Style := psClear; ! end; ! Rectangle(ARect); ! end; end; end; --- 2785,2806 ---- begin Brush.Assign(SelectionFrameBrush); Pen.Assign(SelectionFramePen); + Rectangle(ARect); end else ! if FFlatMenubar then ! begin ! Brush.Color := GetSysColor(COLOR_MENUBAR); ! Brush.Style := bsSolid; ! FillRect(ARect); ! end ! else ! begin ! Brush.Color := clBtnFace; ! Brush.Style := bsSolid; ! Pen.Style := psClear; ! Rectangle(ARect); ! end; end; end; end; *************** *** 3056,3061 **** --- 3065,3077 ---- ); end; + function CheckFlatMenubar: boolean; + const SPI_GETFLATMENU = $1022; + var b: BOOL; + begin + Result:= SystemParametersInfo(SPI_GETFLATMENU, 0, @b, 0) and b; + end; + constructor TJvXPMenuItemPainter.Create(AOwner: TComponent); begin inherited; *************** *** 3075,3080 **** --- 3091,3097 ---- FSeparatorColor := DefaultXPSeparatorColor; FCheckedImageBackColor := DefaultXPCheckedImageBackColor; FCheckedImageBackColorSelected := DefaultXPCheckedImageBackColorSelected; + FFlatMenubar:= CheckFlatMenubar; end; procedure TJvXPMenuItemPainter.UpdateFieldsFromMenu; |
|
Here's a slightly different version of the patch (JvMenus.pas.diff.2) which includes a WM_SETTINGCHANGE handler. |
2004-04-20 17:20
|
JvMenus.pas.diff.2 (2,111 bytes) |
|
I would prefer you post the entire unit (zipped, please) because I don't have a tool to merge or view diff files. |
2004-04-23 05:27
|
JvMenus.pas (103,609 bytes) |
|
As requested, I just attached my modified JvMenus.pas. However, I forgot to zip it. I apologize for botching that; I'd replace it with the zip file, but there doesn't seem to be any way for me to do that. |
|
No problem, I'll check it out |
|
Just curious: how does one set the flat menu style in XP? I just tried on a friends XP and we couldn't see any difference even after changing every visual style we could find... |
|
The one way I know of to change the flat menubar setting is to use SystemParametersInfo with SPI_SETFLATMENU: SystemParametersInfo(SPI_SETFLATMENU, 0, pointer(value), 1); where value is a BOOL (note the bizarre use of pvParam rather than uiParam for passing in the value -- contrary to what I first thought, passing in a pointer to a BOOL will always set Flat Menus to true (unless the pointer is nil), regardless of the value of the BOOL). If the setting was orignally true, changing it to false will cause normal menus (notepad's, for example) to paint the menu text with a background of clBtnFace. However the menubar itself still uses COLOR_MENUBAR. No WM_SETTINGCHANGE is issued. So, apparently adding WM_SETTINGCHANGE handling was pointless. It appears that normal menus test the value of SPI_GETFLATMENU every time they paint text, though the menubar background is not changed until you do something like a theme change. This suggests changing my patch to either 1) check SystemParametersInfo every time the menubar is painted or 2) or look for a WM_THEMECHANGED message and update GFlatMenubar when it is received. Option 2 seems to me to be best. Would you like me to attach a new patched JvMenus (zipped this time)? By the way, there's apparently a bug in XP where if you switch from the Windows XP theme to a saved theme based on the Windows XP theme, SPI_GETFLATMENU returns false, but the menubar background continues to use COLOR_MENUBAR. Note that this breaks normal menus (like notepad's) as well as the TJvXPMenuItemPainter. I just spent way too much time looking for a workaround, but I haven't found anything satisfactory (I suspect a themed app may be able to use GetThemeSysBool(ThemeServices.Theme[teMenu], TMT_FLATMENUS) to stay in sync with XP, but I didn't try it.) |
|
A couple of notes: the SPI_SETFLATMENU should have been: SystemParametersInfo(SPI_SETFLATMENU, 0, pointer(value), SPIF_SENDCHANGE); But it doesn't matter because Windows still doesn't send WM_SETTINGCHANGE. It looks like it instead invalidates all windows, which forces any menus to redraw. Also, I note from here: http://homepages.borland.com/strefethen/index.php?pagename=Main.Delphi7 that Borland has implemented some handling for SPI_GETFLATMENU in Delphi 7. Perhaps someone who has the source for this could peek at it and see what the right way to handle this is. |
|
> The one way I know of to change the flat menubar > setting is to use SystemParametersInfo But isn't there a way to do it in the Windows UI? > Would you like me to attach a new patched JvMenus (zipped this time)? Please do |
|
First, I think the only way to change flat menus through the UI is to change the Desktop Theme. Second, my suggestion of handling WM_THEMECHANGED won't work because the message is sometimes sent too early. In testing a switch from the Windows XP theme to the Classic theme, at the time WM_THEMECHANGED was received, SPI_GETFLATMENU returned true; once the theme change was complete, it returned false. So I'm attaching a patch which tests for flat menus every time a top-level item is drawn. You only really need to test once for each WM_NCPAINT, but the test has to be done before the default handling of WM_NCPAINT (which is where the WM_DRAWITEMs are generated). TJvMainMenu uses an hoAfterMsg hook, so its current hook can't be used. I didn't add a new hook because, on my system anyway, there's no detectable slowdown from testing for each item. By the way, all of this would be much easier if top-level items were not created with MFT_OWNERDRAW (does anyone ever use real owner-drawing (images, etc.) for the items in the menubar itself)? But I don't think there's a good way to get TMenuItem to do that. Anyway, a couple of other things. The test for flat menubars first tests for IsWinXP_UP (I stole the code for this from JvBalloonHint.pas -- you might want to combine this and other similar tests scattered through JVCL into some sort of utility unit). This is because, according to a comment in the Toolbar2000 source, if the proper bit is set in the UserPreferencesMask in the registry, SPI_GETFLATMENU will succeed (and return true) on Windows 2000, even though flat menus are not supported there. Both SPI_GETFLATMENU and COLOR_MENUBAR are likely defined in newer units in rtl\win for versions after Delphi 5; you might want to surround their definitions in JvMenus with IFDEFS so they are only defined there for versions which need them. Finally, I made UseFlatMenubars a public function, because it seemed like someone might want to create their own ItemPainter class, and they would potentially need to check this. |
2004-04-26 11:19
|
JvMenus.zip (18,855 bytes) |
|
I have no way of testing this (stil don't have XP) but I will commit it since that is the only way to get feedback (most users won't try code posted here). |
|
No reply, so assuming it works (already in CVS) |
Date Modified | Username | Field | Change |
---|---|---|---|
2004-04-20 16:23 | glchapman | New Issue | |
2004-04-20 16:23 | glchapman | File Added: JvMenus.pas.diff | |
2004-04-20 17:19 | glchapman | Note Added: 0003974 | |
2004-04-20 17:20 | glchapman | File Added: JvMenus.pas.diff.2 | |
2004-04-23 02:46 |
|
Note Added: 0004029 | |
2004-04-23 05:27 | anonymous | File Added: JvMenus.pas | |
2004-04-23 05:35 | glchapman | Note Added: 0004030 | |
2004-04-23 06:01 |
|
Note Added: 0004032 | |
2004-04-23 06:15 |
|
Note Added: 0004033 | |
2004-04-24 09:58 | glchapman | Note Added: 0004057 | |
2004-04-24 10:40 | glchapman | Note Added: 0004058 | |
2004-04-24 23:55 |
|
Note Added: 0004063 | |
2004-04-24 23:56 |
|
Status | new => feedback |
2004-04-26 11:18 | glchapman | Note Added: 0004087 | |
2004-04-26 11:19 | glchapman | File Added: JvMenus.zip | |
2004-04-27 01:19 |
|
Note Added: 0004092 | |
2004-04-27 01:38 |
|
Status | feedback => assigned |
2004-04-27 01:38 |
|
Assigned To | => user72 |
2004-06-25 05:05 |
|
Status | assigned => resolved |
2004-06-25 05:05 |
|
Resolution | open => fixed |
2004-06-25 05:05 |
|
Note Added: 0004628 |