home *** CD-ROM | disk | FTP | other *** search
Wrap
VERSION 5.00 Object= "{90BE51A2-EA01-11D2-A3B6-000000000000}#1.0#0"; "fsMsgHook5D.ocx" Begin VB.Form Form1 BorderStyle = 3 'Fixed Dialog Caption = "fsMsgHook Demo - Fun with menus" ClientHeight = 3180 ClientLeft = 150 ClientTop = 720 ClientWidth = 4755 LinkTopic = "Form1" MaxButton = 0 'False MinButton = 0 'False ScaleHeight = 3180 ScaleWidth = 4755 ShowInTaskbar = 0 'False StartUpPosition = 3 'Windows Default Begin FishheadMsgHook.fsMsgHook fsMsgHook1 Left = 1320 Top = 930 _ExtentX = 741 _ExtentY = 741 End Begin VB.Label lbl BorderStyle = 1 'Fixed Single Height = 315 Left = 0 TabIndex = 0 Top = 2850 Width = 4755 End Begin VB.Menu mnu_File Caption = "&File" Begin VB.Menu mnuF_Exit Caption = "E&xit" End End Begin VB.Menu mnu_Now Caption = "&Now" Begin VB.Menu mnuN_Caption Caption = "?" End End Begin VB.Menu mnu_Colors Caption = "&Colors" Begin VB.Menu mnuC_Red Caption = "&Red" End Begin VB.Menu mnuC_White Caption = "&White" End Begin VB.Menu mnuC_Blue Caption = "&Blue" End End Attribute VB_Name = "Form1" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False ' ************************************************************** ' ** Created by: Fishhead Software ' ** URL: http://www.fishware.com ' ** mailto://support@fishware.com ' **------------------------------------------------------------ ' ** Project: fsMsgHook Demo ' ** Version: 1.00 ' ** Description: Fun with menus ' ** This demo shows some of the neat menu tricks you can do if ' ** you have access to Windows messaging. fsMsgHook gives you ' ** just that capability. With fsMsgHook you can access almost ' ** any window message for any window. All you need is the ' ** window handle, the message, and little information about ' ** wParam and lParam for the message. ' ** This demo includes the following four examples: ' ** - How to add an item and respond to the forms system menu; ' ** - Display a message as the user changes the menu selection; ' ** - Change the width of menu item and have it displayed correctly; ' ** - Add ownerdraw of a submenu; ' ** Of course there are more things you can do with messages than ' ** just change the way menus work. For example: you can limit the ' ** form size, change how it paints, add multicolor to listboxes ' ** to name a few. ' **------------------------------------------------------------ ' ** Notes: July 24, 1998 Created ' ************************************************************** Option Explicit 'Windows constants Private Const COLOR_HIGHLIGHT = 13 Private Const COLOR_MENU = 4 Private Const COLOR_WINDOW = 5 Private Const MF_BYCOMMAND = &H0 Private Const MF_OWNERDRAW = &H100 Private Const MF_SEPARATOR = &H800 Private Const MF_STRING = &H0 Private Const ODS_SELECTED = &H1 Private Const ODT_MENU = 1 Private Const SM_CYMENU = 15 Private Const SC_CLOSE = &HF060 Private Const SC_MAXIMIZE = &HF030 Private Const SC_MINIMIZE = &HF020 Private Const SC_MOVE = &HF010 Private Const SC_RESTORE = &HF120 Private Const SC_SIZE = &HF000 ' Menu messages Private Const WM_DRAWITEM = &H2B Private Const WM_INITMENUPOPUP = &H117 Private Const WM_MEASUREITEM = &H2C Private Const WM_MENUSELECT = &H11F Private Const WM_SYSCOMMAND = &H112 Private Type Rect Left As Long Top As Long Right As Long Bottom As Long End Type Private Type DRAWITEMSTRUCT CtlType As Long CtlID As Long ItemID As Long ItemAction As Long ItemState As Long hwndItem As Long hDC As Long rcItem As Rect ItemData As Long End Type Private Type MEASUREITEMSTRUCT CtlType As Long CtlID As Long ItemID As Long ItemWidth As Long ItemHeight As Long ItemData As Long End Type ' Windows declarations Private Declare Function AppendMenu Lib "user32" Alias "AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal lpNewItem As String) As Long Private Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long Private Declare Function FillRect Lib "user32" (ByVal hDC As Long, lpRect As Rect, ByVal hBrush As Long) As Long Private Declare Function GetMenu Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function GetSubMenu Lib "user32" (ByVal hMenu As Long, ByVal nPos As Long) As Long Private Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long Private Declare Function InflateRect Lib "user32" (lpRect As Rect, ByVal x As Long, ByVal y As Long) As Long Private Declare Function ModifyMenu Lib "user32" Alias "ModifyMenuA" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long, ByVal wIDNewItem As Long, ByVal nValue As Any) As Long Private Declare Function Rectangle Lib "gdi32" (ByVal hDC As Long, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long Private Declare Sub RtlMoveMemory Lib "Kernel32" (lpDest As Any, lpSource As Any, ByVal nCount As Long) Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long ' ******************************** ' ** fsMsgHook Demo variables ' ******************************** Private Const menuRed = 6 Private Const menuWhite = 7 Private Const menuBlue = 8 ' fsMsgHook about system menu id Private Const IDM_ABOUT = 10 Private Const SC_ABOUT = &HA Private m_hSysMenu As Long Private m_hMenu As Long Private m_Counter As Integer Private Sub Form_Load() Dim hCMenu As Long ' Add separator and fsMsgHook About menu item m_hSysMenu = GetSystemMenu(Me.hwnd, False) Call AppendMenu(m_hSysMenu, MF_SEPARATOR, 0, 0&) Call AppendMenu(m_hSysMenu, MF_STRING, IDM_ABOUT, "&About...") ' Get handle to "Colors" menu m_hMenu = GetMenu(Me.hwnd) hCMenu = GetSubMenu(m_hMenu, 2) ' Make the colors Call ModifyMenu(hCMenu, menuRed, MF_BYCOMMAND Or MF_OWNERDRAW, menuRed, vbRed) Call ModifyMenu(hCMenu, menuWhite, MF_BYCOMMAND Or MF_OWNERDRAW, menuWhite, vbWhite) Call ModifyMenu(hCMenu, menuBlue, MF_BYCOMMAND Or MF_OWNERDRAW, menuBlue, vbBlue) fsMsgHook1.Add hwnd ' ************************************************** ' ** Now add the messages for this window that needs ' ** to be act on. Of course, this is optional, ' ** because in the WindProc event, the code is ' ** using a select case which will filter out ' ** unwanted messages. ' ************************************************* fsMsgHook1.Messages().Add WM_DRAWITEM fsMsgHook1.Messages().Add WM_INITMENUPOPUP fsMsgHook1.Messages().Add WM_MEASUREITEM fsMsgHook1.Messages().Add WM_MENUSELECT fsMsgHook1.Messages().Add WM_SYSCOMMAND End Sub Private Sub fsMsgHook1_WndProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long, bForward As Boolean, Result As Long) Dim DrawItem As DRAWITEMSTRUCT Dim MeasureItem As MEASUREITEMSTRUCT Dim hBrush As Long, hOldBrush As Long Dim menuItemRect As Rect Dim adjust As Long Dim i As Long Dim width As Long Select Case uMsg Case WM_INITMENUPOPUP ' ********************************* ' ** Adjust the NOW menu contents ' ** before windows calculates the ' ** menu width, otherwise the menu ' ** may not be wide enough. ' ********************************* Select Case fsLoWord(lParam) Case 1 ' NOW menu item m_Counter = m_Counter + 1 Select Case m_Counter Case 1 mnuN_Caption.Caption = Date Case 2 mnuN_Caption.Caption = Time Case 3 mnuN_Caption.Caption = Now m_Counter = 0 End Select ' Tell fsMsgHook to get rid of the message bForward = False End Select Case WM_DRAWITEM If wParam = 0 Then ' Get DrawItemStruct Call RtlMoveMemory(DrawItem, ByVal lParam, Len(DrawItem)) ' Determine if it is for the menu and which menu items If DrawItem.CtlType = ODT_MENU Then If DrawItem.ItemID >= menuRed And DrawItem.ItemID <= menuBlue Then menuItemRect = DrawItem.rcItem ' Paint background color first If DrawItem.ItemState And ODS_SELECTED Then hBrush = CreateSolidBrush(vbGreen) Else hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU)) End If Call FillRect(DrawItem.hDC, menuItemRect, hBrush) Call DeleteObject(hBrush) ' Now draw color item sub bar hBrush = CreateSolidBrush(DrawItem.ItemData) hOldBrush = SelectObject(DrawItem.hDC, hBrush) adjust = (menuItemRect.Bottom - menuItemRect.Top) / 4 Call InflateRect(menuItemRect, -adjust, -adjust) width = menuItemRect.Right - menuItemRect.Left ' Make six boxes for each menu item For i = 0 To 5 menuItemRect.Right = menuItemRect.Left + (width \ 6) - 6 Call Rectangle(DrawItem.hDC, menuItemRect.Left, menuItemRect.Top, menuItemRect.Right, menuItemRect.Bottom) menuItemRect.Left = menuItemRect.Right + 6 Next ' Clean up Call SelectObject(DrawItem.hDC, hOldBrush) Call DeleteObject(hBrush) ' Tell fsMsgHook to get rid of the message bForward = False End If End If End If Case WM_MEASUREITEM ' Get MEASUREITEMSTRUCT Call RtlMoveMemory(MeasureItem, ByVal lParam, Len(MeasureItem)) ' Make the menu items big MeasureItem.ItemWidth = 200 MeasureItem.ItemHeight = GetSystemMetrics(SM_CYMENU) * 2 'Save MEASUREITEMSTRUCT Call RtlMoveMemory(ByVal lParam, MeasureItem, Len(MeasureItem)) ' Tell fsMsgHook to get rid of the message bForward = False Case WM_SYSCOMMAND If wParam = IDM_ABOUT Then fsMsgHook1.About End If Case WM_MENUSELECT Select Case lParam Case m_hSysMenu Select Case fsLoWord(wParam) Case SC_RESTORE lbl.Caption = "Restore this window to normal size." Case SC_MOVE lbl.Caption = "Move this window." Case SC_SIZE lbl.Caption = "Resize this window." Case SC_MINIMIZE lbl.Caption = "Minimize this window." Case SC_MAXIMIZE lbl.Caption = "Maximize this window." Case SC_CLOSE lbl.Caption = "Exit fsMsgHook demo." Case IDM_ABOUT lbl.Caption = "fsMsgHook About dialog." End Select Case m_hMenu Select Case fsLoWord(wParam) Case 0 lbl.Caption = mnu_File.Caption Case 1 lbl.Caption = mnu_Now.Caption Case 2 lbl.Caption = mnu_Colors.Caption End Select Case Else Select Case fsLoWord(wParam) Case 2 lbl.Caption = "Exit fsMsgHook demo." Case 4 Select Case m_Counter Case 1 lbl.Caption = "Date" Case 2 lbl.Caption = "Time" Case Else lbl.Caption = "Now" End Select Case menuRed lbl.Caption = "Red" Case menuWhite lbl.Caption = "White" Case menuBlue lbl.Caption = "Blue" End Select End Select End Select End Sub ' ********************************************************* ' ** fsHiWord This routine will return the first two bytes ' ** of a DWord or Long; ' ** ------------------------------------------------------ ' ** Value The DWord or Long value ' ********************************************************* Public Function fsHiWord(Value As Long) As Long fsHiWord = (Value And &HFFFF0000) \ 65536 End Function ' ********************************************************* ' ** fsLoWord This routine will return the last two bytes ' ** of a DWord or Long; ' ** ------------------------------------------------------ ' ** Value The DWord or Long value ' ********************************************************* Public Function fsLoWord(Value As Long) As Long If Value And &H8000& Then fsLoWord = Value Or &HFFFF0000 Else fsLoWord = Value And &HFFFF& End If End Function Private Sub mnuF_Exit_Click() Unload Me End Sub