I have finally started trying to work with MDI.
I started with Petzold's demo as translated by Keith Waters.
I just followed the patterns and added a menu call New Data and added a window with it's own windows procedure.
It will show the static and edit registered classes but it won't move from field to field using the tab key.
It's pretty much all SDK and I'm stumped. The following will compile on 7.04.
I think it has to do with the program message pump. Just need a little help.
Here it is:
MDIDEMO.INC 'seems to just hold the MDIDEMO.H info
Thanks,
Bob Mechler
I started with Petzold's demo as translated by Keith Waters.
I just followed the patterns and added a menu call New Data and added a window with it's own windows procedure.
It will show the static and edit registered classes but it won't move from field to field using the tab key.
It's pretty much all SDK and I'm stumped. The following will compile on 7.04.
I think it has to do with the program message pump. Just need a little help.
Here it is:
Code:
' ' ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß ' Û Û Ûßß Û ßÛß Û Û Û Û Û ÛßÛ ßÛß Ûßß ÛßÛ ÛßÛ 51 Broxholm Road ' ÛÜÝ ÛÜ Û Û ÛÜÛ Û Û Û ÛÜÛ Û ÛÜ ÛÜß ßþÜ London SE27 ONA ' Û Û ÛÜÜ Û Û Û Û ßÜßÜß Û Û Û ÛÜÜ Û Û ÛÜÛ ' ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ ' ' ' PROPERTY.BAS ------------------------------------ (c) Keith A. Waters 1998 ' ' This program is a translation from C of the program MDIDEMO.C described and ' analysed in Chapter 18 of Charles Petzold's book, Programming Windows 95. ' $COMPILE EXE "HWADEMO" 'Compile to an executable $DEBUG ERROR ON $DIM ALL $RESOURCE "MDIDEMO.PBR" 'Resource binary $INCLUDE "WIN32API.INC" 'C:\PBDLL32\WINAPI\WIN32API.INC' $INCLUDE "MDIDEMO.INC" ' Structure for storing data unique to each Hello child window ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TYPE HELLODATA iColor AS LONG clrText AS LONG END TYPE ' Structure for storing data unique to each Rect child window ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TYPE RECTDATA cxClient AS LONG cyClient AS LONG END TYPE ' Global variables ' ~~~~~~~~~~~~~~~~ GLOBAL szFrameClass AS ASCIIZ*9,_ szHelloClass AS ASCIIZ*15,_ szRectClass AS ASCIIZ*13,_ szDataClass AS ASCIIZ*13,_ hInst AS LONG,_ hMenuInit AS LONG,_ hMenuHello AS LONG,_ hMenuRect AS LONG,_ hMenuData AS LONG,_ hMenuInitWindow AS LONG,_ hMenuHelloWindow AS LONG,_ hMenuRectWindow AS LONG,_ hMenuDataWindow AS LONG DECLARE FUNCTION IAssign (BYVAL iCont AS LONG, _ BYVAL value1 AS LONG, BYVAL value2 AS LONG) AS LONG DECLARE FUNCTION RndInt (x AS LONG) AS LONG ' --------------------------------------------------------------------- 'FUNCTION WinMain (BYVAL hCurrInstance AS LONG,_ ' BYVAL hPrevInstance AS LONG,_ ' lpCmdLine AS ASCIIZ PTR,_ ' BYVAL iCmdShow AS LONG) AS LONG ' ' hCurrInstance AS LONG instance handle - a number that uniquely ' identifies program while it is running ' hPrevInstance AS LONG previous instance - obsolete under Windows 95 ' lpCmdLine AS ASCIIZ PTR command-line parameters used with program ' iCmdShow AS LONG number indicating how window should be ' initially displayed. Takes values ' %SW_SHOWNORMAL or %SW_SHOWMINNOACTIVE. ' ' This function is the entry point to the program. If the function ' succeeds, terminating when it receives a WM_QUIT message, it should ' return the exit value contained in that message's wParam parameter. ' If the function terminates before entering the message loop, it should ' return zero. ' FUNCTION WINMAIN (BYVAL hCurrInstance AS LONG,_ BYVAL hPrevInstance AS LONG,_ BYVAL lpCmdLine AS ASCIIZ PTR,_ BYVAL iCmdShow AS LONG) AS LONG LOCAL msg AS TAGMSG,_ wClass AS WNDCLASSEX,_ hWndFrame AS DWORD,_ hWndClient AS DWORD,_ hAccel AS LONG ' Initialize ' ~~~~~~~~~~ hInst = hCurrInstance szFrameClass = "MdiFrame" szHelloClass = "MdiHelloChild" szRectClass = "MdiRectChild" 'research szDataClass = "MdiDataChild" IF 0 = hPrevInstance THEN 'If first instance ' Register the frame window class ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wClass.cbSize = SIZEOF(wClass) wClass.style = %CS_HREDRAW OR %CS_VREDRAW wClass.lpfnWndProc = CODEPTR(FrameWndProc) wClass.cbClsExtra = 0 wClass.cbWndExtra = 0 wClass.hInstance = hCurrInstance wClass.hIcon = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) wClass.hCursor = LoadCursor(%NULL, BYVAL %IDC_ARROW) wClass.hbrBackground = %COLOR_APPWORKSPACE + 1 wClass.lpszMenuName = %NULL wClass.lpszClassName = VARPTR(szFrameClass) wClass.hIConSm = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) CALL RegisterClassEx (wClass) ' Register the Hello child window class ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wClass.cbSize = SIZEOF(wClass) wClass.style = %CS_HREDRAW OR %CS_VREDRAW wClass.lpfnWndProc = CODEPTR(HelloWndProc) wClass.cbClsExtra = 0 wClass.cbWndExtra = SIZEOF(hWndFrame) 'We will store pointer here wClass.hInstance = hCurrInstance wClass.hIcon = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) wClass.hCursor = LoadCursor(%NULL, BYVAL %IDC_ARROW) wClass.hbrBackground = GetStockObject(%WHITE_BRUSH) wClass.lpszMenuName = %NULL wClass.lpszClassName = VARPTR(szHelloClass) wClass.hIConSm = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) CALL RegisterClassEx (wClass) ' Register the Rect child window class ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wClass.cbSize = SIZEOF(wClass) wClass.style = %CS_HREDRAW OR %CS_VREDRAW wClass.lpfnWndProc = CODEPTR(RectWndProc) wClass.cbClsExtra = 0 wClass.cbWndExtra = SIZEOF(hWndFrame) 'We will store pointer here wClass.hInstance = hCurrInstance wClass.hIcon = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) wClass.hCursor = LoadCursor(%NULL, BYVAL %IDC_ARROW) wClass.hbrBackground = GetStockObject(%WHITE_BRUSH) wClass.lpszMenuName = %NULL wClass.lpszClassName = VARPTR(szRectClass) wClass.hIConSm = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) CALL RegisterClassEx (wClass) ' Register the Data child window class ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ wClass.cbSize = SIZEOF(wClass) wClass.style = %CS_HREDRAW OR %CS_VREDRAW wClass.lpfnWndProc = CODEPTR(DataWndProc) wClass.cbClsExtra = 0 wClass.cbWndExtra = SIZEOF(hWndFrame) 'We will store pointer here wClass.hInstance = hCurrInstance wClass.hIcon = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) wClass.hCursor = LoadCursor(%NULL, BYVAL %IDC_ARROW) wClass.hbrBackground = GetStockObject(%WHITE_BRUSH) wClass.lpszMenuName = %NULL wClass.lpszClassName = VARPTR(szDataClass) wClass.hIConSm = LoadIcon (%NULL, BYVAL %IDI_APPLICATION) CALL RegisterClassEx (wClass) END IF ' Obtain handles to three possible menus ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hMenuInit = LoadMenu (hInst, "MdiMenuInit") 'Menu for Frame window alone hMenuHello = LoadMenu (hInst, "MdiMenuHello") 'Menu for Hello child window hMenuRect = LoadMenu (hInst, "MdiMenuRect") 'Menu for Rect child window hMenuData = LoadMenu (hInst, "MdiMenuData") 'Menu for Data child window ' Obtain handles to the "Window" submenus ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ hMenuInitWindow = GetSubMenu (hMenuInit, %INIT_MENU_POS) '..on Frame menu hMenuHelloWindow = GetSubMenu (hMenuHello, %HELLO_MENU_POS) '..on Hello menu hMenuRectWindow = GetSubMenu (hMenuRect, %RECT_MENU_POS) '..on Rect menu hMenuDataWindow = GetSubMenu (hMenuData, %DATA_MENU_POS) '..on Data menu ' Load accelerator table ' ~~~~~~~~~~~~~~~~~~~~~~ hAccel = LoadAccelerators (hInst, "MdiAccel") ' Create the Frame window ' ~~~~~~~~~~~~~~~~~~~~~~~ hwndFrame = CreateWindow (szFrameClass, "MDI Demonstration",_ %WS_OVERLAPPEDWINDOW OR %WS_CLIPCHILDREN,_ %CW_USEDEFAULT, %CW_USEDEFAULT,_ %CW_USEDEFAULT, %CW_USEDEFAULT,_ %NULL, hMenuInit, hCurrInstance, %NULL) hwndClient = GetWindow (hwndFrame, %GW_CHILD) ' Display Frame window ' ~~~~~~~~~~~~~~~~~~~~ CALL ShowWindow (hwndFrame, iCmdShow) CALL UpdateWindow (hwndFrame) ' Main message loop of program ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ WHILE GetMessage(msg, %NULL, 0, 0) IF TranslateMDISysAccel(hWndClient, msg) OR _ TranslateAccelerator(hWndFrame, hAccel, msg) THEN 'Skip ELSE CALL TranslateMessage (msg) 'translates some keyboard messages CALL DispatchMessage (msg) 'sends a message to a window procedure END IF WEND ' while GetMessage( Msg, byval %Null, 0, 0 ) ' if TranslateMDISysAccel(hWndClient, Msg) = 0 then ' if hAccel = 0 or TranslateAccelerator( hWnd, hAccel, Msg ) = 0 then ' hWndChild = MdiGetActive(hWndClient ) ' if hWndChild then ' hWndChild = GetProp( hWndChild , "DDT_DLG" ) ' if hWndChild then ' if IsDialogMessage( hWndChild, Msg ) then iterate ' end if ' end if ' TranslateMessage Msg ' DispatchMessage Msg ' end if ' end if ' wend ' Clean up and assign return value ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CALL DestroyMenu (hMenuHello) CALL DestroyMenu (hMenuRect) CALL DestroyMenu (hMenuData) FUNCTION = Msg.wParam END FUNCTION ' ---------------------------------------------------------------------- 'FUNCTION FrameWndProc (BYVAL hWnd AS DWORD,_ ' BYVAL iMsg AS DWORD,_ ' BYVAL wParam AS DWORD,_ ' BYVAL lParam AS DWORD) EXPORT AS LONG ' ' BYVAL hWnd AS DWORD handle of window to which message is directed ' BYVAL iMsg AS DWORD message identifier, eg. %WM_LBUTTONDOWN ' BYVAL wParam AS DWORD message parameter (meaning depends on message) ' BYVAL lParam AS DWORD message parameter (meaning depends on message) ' ' This function is the "window procedure" for program's Frame window. ' The function is called by Windows (it is a "CALLBACK" function). ' The function returns zero for all messages processed internally rather ' than by the default window procedure, DefFrameProc. ' FUNCTION FrameWndProc (BYVAL hWnd AS DWORD,_ BYVAL iMsg AS DWORD,_ BYVAL wParam AS DWORD,_ BYVAL lParam AS DWORD) EXPORT AS LONG STATIC hwndClient AS LONG LOCAL clientCreate AS CLIENTCREATESTRUCT,_ mdiCreate AS MDICREATESTRUCT,_ hwndChild AS LONG,_ szTitle AS ASCIIZ*11 SELECT CASE iMsg CASE %WM_CREATE 'Create the Client window (preregistered class) clientCreate.hWindowMenu = hMenuInitWindow 'See PW95, 952 clientCreate.idFirstChild = %IDM_FIRSTCHILD ' hwndClient = CreateWindow ("MDICLIENT", BYVAL %NULL,_ %WS_CHILD OR %WS_CLIPCHILDREN OR %WS_VISIBLE,_ 0, 0, 0, 0, hwnd, 1, hInst,_ VARPTR(clientCreate)) FUNCTION = 0 CASE %WM_COMMAND SELECT CASE wParam CASE %IDM_NEWHELLO 'Create a Hello child window szTitle = "Hello" mdiCreate.szClass = VARPTR(szHelloClass) mdiCreate.szTitle = VARPTR(szTitle) mdiCreate.hOwner = hInst mdiCreate.x = %CW_USEDEFAULT mdiCreate.y = %CW_USEDEFAULT mdiCreate.cx = %CW_USEDEFAULT mdiCreate.cy = %CW_USEDEFAULT mdiCreate.style = 0 mdiCreate.lParam = 0 hwndChild = SendMessage (hwndClient, %WM_MDICREATE, 0,_ VARPTR(mdiCreate)) FUNCTION = 0 CASE %IDM_NEWRECT 'Create a Rect child window szTitle = "Rectangles" mdiCreate.szClass = VARPTR(szRectClass) mdiCreate.szTitle = VARPTR(szTitle) mdiCreate.hOwner = hInst mdiCreate.x = %CW_USEDEFAULT mdiCreate.y = %CW_USEDEFAULT mdiCreate.cx = %CW_USEDEFAULT mdiCreate.cy = %CW_USEDEFAULT mdiCreate.style = 0 mdiCreate.lParam = 0 hwndChild = SendMessage (hwndClient, %WM_MDICREATE, 0,_ VARPTR(mdiCreate)) FUNCTION = 0 CASE %IDM_NEWDATA 'Create a Rect child window szTitle = "Data Entry" mdiCreate.szClass = VARPTR(szDataClass) mdiCreate.szTitle = VARPTR(szTitle) mdiCreate.hOwner = hInst mdiCreate.x = %CW_USEDEFAULT mdiCreate.y = %CW_USEDEFAULT mdiCreate.cx = %CW_USEDEFAULT mdiCreate.cy = %CW_USEDEFAULT mdiCreate.style = 0 mdiCreate.lParam = 0 hwndChild = SendMessage (hwndClient, %WM_MDICREATE, 0,_ VARPTR(mdiCreate)) FUNCTION = 0 CASE %IDM_CLOSE 'Close the active window hwndChild = SendMessage (hwndClient, %WM_MDIGETACTIVE, 0, 0) IF SendMessage(hwndChild, %WM_QUERYENDSESSION, 0, 0) THEN CALL SendMessage (hwndClient, %WM_MDIDESTROY, hwndChild, 0) END IF FUNCTION = 0 CASE %IDM_EXIT 'Exit the program CALL SendMessage (hwnd, %WM_CLOSE, 0, 0) FUNCTION = 0 CASE %IDM_TILE 'Messages for arranging windows CALL SendMessage (hwndClient, %WM_MDITILE, 0, 0) FUNCTION = 0 CASE %IDM_CASCADE CALL SendMessage (hwndClient, %WM_MDICASCADE, 0, 0) FUNCTION = 0 CASE %IDM_ARRANGE CALL SendMessage (hwndClient, %WM_MDIICONARRANGE, 0, 0) FUNCTION = 0 CASE %IDM_CLOSEALL 'Attempt to close all children CALL EnumChildWindows (hwndClient, CODEPTR(CloseEnumProc), 0) FUNCTION = 0 CASE ELSE 'Pass to active child... hwndChild = SendMessage (hwndClient, %WM_MDIGETACTIVE, 0, 0) IF IsWindow (hwndChild) THEN CALL SendMessage (hwndChild, %WM_COMMAND, wParam, lParam) END IF FUNCTION = DefFrameProc (hwnd, hwndClient, iMsg, wParam, lParam) END SELECT CASE %WM_QUERYENDSESSION, %WM_CLOSE 'Attempt to close all children CALL SendMessage (hwnd, %WM_COMMAND, %IDM_CLOSEALL, 0) IF %NULL <> GetWindow (hwndClient, %GW_CHILD) THEN FUNCTION = 0 ELSE FUNCTION = DefFrameProc (hwnd, hwndClient, iMsg, wParam, lParam) END IF CASE %WM_DESTROY CALL PostQuitMessage (0) FUNCTION = 0 CASE ELSE FUNCTION = DefFrameProc (hwnd, hwndClient, iMsg, wParam, lParam) END SELECT END FUNCTION ' -------------------------------------------------------------------- FUNCTION CloseEnumProc (BYVAL hwnd AS DWORD, BYVAL lParam AS DWORD) AS LONG IF GetWindow (hwnd, %GW_OWNER) THEN 'Check for icon title 'Do nothing ELSE CALL SendMessage (GetParent(hwnd), %WM_MDIRESTORE, hwnd, 0) IF 0 <> SendMessage(hwnd, %WM_QUERYENDSESSION, 0, 0) THEN CALL SendMessage (GetParent(hwnd), %WM_MDIDESTROY, hwnd, 0) END IF END IF FUNCTION = 1 END FUNCTION ' -------------------------------------------------------------------- 'FUNCTION HelloWndProc (BYVAL hwnd AS DWORD, BYVAL iMsg AS DWORD, _ ' BYVAL wParam AS DWORD, BYVAL lParam AS DWORD) EXPORT AS LONG ' ' This function is the window procedure for the child window that displays ' "Hello world". ' FUNCTION HelloWndProc (BYVAL hwnd AS DWORD, BYVAL iMsg AS DWORD, _ BYVAL wParam AS DWORD, BYVAL lParam AS DWORD) EXPORT AS LONG STATIC hwndClient AS LONG,_ hwndFrame AS LONG,_ clrTextArray() AS LONG LOCAL hdc AS LONG,_ hMenu AS LONG,_ lpHelloData AS HELLODATA PTR,_ ps AS PAINTSTRUCT,_ rrect AS RECT DIM clrTextArray(0: 4) SELECT CASE iMsg CASE %WM_CREATE clrTextArray(0) = RGB(0, 0, 0) clrTextArray(1) = RGB(255, 0, 0) clrTextArray(2) = RGB(0, 255, 0) clrTextArray(3) = RGB(0, 0, 255) clrTextArray(4) = RGB(255, 255, 255) ' Allocate memory for window private data ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lpHelloData = HeapAlloc (GetProcessHeap(), %HEAP_ZERO_MEMORY,_ SIZEOF (@lpHelloData)) @lpHelloData.iColor = %IDM_BLACK @lpHelloData.clrText = RGB (0, 0, 0) CALL SetWindowLong (hwnd, 0, lpHelloData) ' Save some window handles ' ~~~~~~~~~~~~~~~~~~~~~~~~ hwndClient = GetParent (hwnd) hwndFrame = GetParent (hwndClient) FUNCTION = 0 CASE %WM_COMMAND SELECT CASE wParam CASE %IDM_BLACK, %IDM_RED, %IDM_GREEN, %IDM_BLUE, %IDM_WHITE 'Change the text color lpHelloData = GetWindowLong (hwnd, 0) hMenu = GetMenu (hwndFrame) CALL CheckMenuItem (hMenu, @lpHelloData.iColor, %MF_UNCHECKED) @lpHelloData.iColor = wParam CALL CheckMenuItem (hMenu, @lpHelloData.iColor, %MF_CHECKED) @lpHelloData.clrText = clrTextArray(wParam - %IDM_BLACK) CALL InvalidateRect (hwnd, BYVAL %NULL, %FALSE) END SELECT FUNCTION = 0 CASE %WM_PAINT 'Paint the window hdc = BeginPaint (hwnd, ps) lpHelloData = GetWindowLong (hwnd, 0) CALL SetTextColor (hdc, @lpHelloData.clrText) CALL GetClientRect (hwnd, rrect) CALL DrawText (hdc, "Hello, World!", -1, rrect,_ %DT_SINGLELINE OR %DT_CENTER OR %DT_VCENTER) CALL EndPaint (hwnd, ps) FUNCTION = 0 CASE %WM_MDIACTIVATE ' Set the Hello menu if gaining focus ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IF lParam = hwnd THEN CALL SendMessage (hwndClient, %WM_MDISETMENU,_ hMenuHello, hMenuHelloWindow) END IF ' Check or uncheck menu item ' ~~~~~~~~~~~~~~~~~~~~~~~~~~ lpHelloData = GetWindowLong (hwnd, 0) CALL CheckMenuItem (hMenuHello, @lpHelloData.iColor,_ IAssign(lParam = hwnd, %MF_CHECKED, %MF_UNCHECKED)) ' Set the Init menu if losing focus ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IF lParam <> hwnd THEN CALL SendMessage (hwndClient, %WM_MDISETMENU, hMenuInit,_ hMenuInitWindow) END IF CALL DrawMenuBar (hwndFrame) FUNCTION = 0 CASE %WM_QUERYENDSESSION, %WM_CLOSE IF %IDOK <> MessageBox (hwnd, "OK to close window?", "Hello",_ %MB_ICONQUESTION OR %MB_OKCANCEL) THEN FUNCTION = 0 ELSE FUNCTION = DefMDIChildProc (hwnd, iMsg, wParam, lParam) END IF CASE %WM_DESTROY lpHelloData = GetWindowLong (hwnd, 0) CALL HeapFree (GetProcessHeap(), 0, lpHelloData) FUNCTION = 0 CASE ELSE FUNCTION = DefMDIChildProc (hwnd, iMsg, wParam, lParam) END SELECT END FUNCTION ' ------------------------------------------------------------------- 'FUNCTION RectWndProc (BYVAL hwnd AS DWORD, BYVAL iMsg AS DWORD,_ ' BYVAL wParam AS DWORD, BYVAL lParam AS DWORD) EXPORT AS LONG ' ' This function is the window procedure for the child window that displays ' random rectangles. ' FUNCTION RectWndProc (BYVAL hwnd AS DWORD, BYVAL iMsg AS DWORD,_ BYVAL wParam AS DWORD, BYVAL lParam AS DWORD) EXPORT AS LONG STATIC hwndClient AS LONG,_ hwndFrame AS LONG LOCAL hBrush AS LONG,_ hdc AS LONG,_ lpRectData AS RECTDATA PTR,_ ps AS PAINTSTRUCT,_ xLeft AS LONG,_ xRight AS LONG,_ yTop AS LONG,_ yBottom AS LONG,_ nRed AS LONG,_ nGreen AS LONG,_ nBlue AS LONG SELECT CASE iMsg CASE %WM_CREATE ' Allocate memory for window private data ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ lpRectData = HeapAlloc (GetProcessHeap(), %HEAP_ZERO_MEMORY,_ SIZEOF(@lpRectData)) CALL SetWindowLong (hwnd, 0, lpRectData) ' Start the timer going ' ~~~~~~~~~~~~~~~~~~~~~ CALL SetTimer (hwnd, 1, 2, %NULL) ' Save some window handles ' ~~~~~~~~~~~~~~~~~~~~~~~~ hwndClient = GetParent (hwnd) hwndFrame = GetParent (hwndClient) FUNCTION = 0 CASE %WM_SIZE 'If not minimized, save the window size IF wParam <> %SIZE_MINIMIZED THEN lpRectData = GetWindowLong (hwnd, 0) @lpRectData.cxClient = LOWRD (lParam) @lpRectData.cyClient = HIWRD (lParam) END IF FUNCTION = DefMDIChildProc (hwnd, iMsg, wParam, lParam) CASE %WM_TIMER 'Display a random rectangle lpRectData = GetWindowLong (hwnd, 0) xLeft = RndInt(@lpRectData.cxClient) xRight = RndInt(@lpRectData.cxClient) yTop = RndInt(@lpRectData.cyClient) yBottom = RndInt(@lpRectData.cyClient) nRed = RndInt(255) nGreen = RndInt(255) nBlue = RndInt(255) hdc = GetDC (hwnd) hBrush = CreateSolidBrush (RGB(nRed, nGreen, nBlue)) CALL SelectObject (hdc, hBrush) CALL Rectangle (hdc, MIN(xLeft, xRight), MIN(yTop, yBottom),_ MAX(xLeft, xRight), MAX(yTop, yBottom)) CALL ReleaseDC (hwnd, hdc) CALL DeleteObject (hBrush) FUNCTION = 0 CASE %WM_PAINT 'Clear the window CALL InvalidateRect (hwnd, BYVAL %NULL, %TRUE) hdc = BeginPaint (hwnd, ps) CALL EndPaint (hwnd, ps) FUNCTION = 0 CASE %WM_MDIACTIVATE 'Set the appropriate menu IF lParam = hwnd THEN CALL SendMessage (hwndClient, %WM_MDISETMENU, hMenuRect,_ hMenuRectWindow) ELSE CALL SendMessage (hwndClient, %WM_MDISETMENU, hMenuInit,_ hMenuInitWindow) END IF CALL DrawMenuBar (hwndFrame) FUNCTION = 0 CASE %WM_DESTROY lpRectData = GetWindowLong (hwnd, 0) CALL HeapFree (GetProcessHeap(), 0, lpRectData) CALL KillTimer (hwnd, 1) FUNCTION = 0 CASE ELSE FUNCTION = DefMDIChildProc (hwnd, iMsg, wParam, lParam) END SELECT END FUNCTION ' ---------------------------------------------------------------------- 'FUNCTION IAssign (BYVAL iCont AS LONG, _ ' BYVAL value1 AS LONG, BYVAL value2 AS LONG) AS LONG ' iCont AS LONG conditional variable or expression ' value1 AS LONG return value ' value2 AS LONG alternate return value ' ' Returns value1 if iCont is true (non-zero), otherwise returns value2. ' The function allows simulation of a C statement of the form (eg.), ' ' iVal = iAttr & EZ_ATTR_ITALIC ? 1 : 0 ; ' ' with ' ' iVal = IAssign (iAttr AND %EZ_ATTR_ITALIC, 1, 0) ' FUNCTION DataWndProc (BYVAL hwnd AS DWORD, BYVAL iMsg AS DWORD,_ BYVAL wParam AS DWORD, BYVAL lParam AS DWORD) EXPORT AS LONG STATIC hwndClient AS LONG,_ hwndFrame AS LONG,_ clrTextArray() AS LONG LOCAL hdc AS LONG,_ hMenu AS LONG,_ lpHelloData AS HELLODATA PTR,_ ps AS PAINTSTRUCT,_ rrect AS RECT,_ hLblName1 AS LONG,_ hTxtName1 AS LONG,_ hLblName2 AS LONG,_ hTxtName2 AS LONG,_ txt AS ASCIIZ * %MAX_PATH,_ stxt AS STRING,_ szClassName AS ASCIIZ * %MAX_PATH,_ hFont AS LONG,_ hRetV AS LONG DIM clrTextArray(0: 4) SELECT CASE iMsg CASE %WM_CREATE ' clrTextArray(0) = RGB(0, 0, 0) ' clrTextArray(1) = RGB(255, 0, 0) ' clrTextArray(2) = RGB(0, 255, 0) ' clrTextArray(3) = RGB(0, 0, 255) ' clrTextArray(4) = RGB(255, 255, 255) ' Allocate memory for window private data ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' lpHelloData = HeapAlloc (GetProcessHeap(), %HEAP_ZERO_MEMORY,_ ' SIZEOF (@lpHelloData)) ' @lpHelloData.iColor = %IDM_BLACK ' @lpHelloData.clrText = RGB (0, 0, 0) ' CALL SetWindowLong (hwnd, 0, lpHelloData) ' Save some window handles ' ~~~~~~~~~~~~~~~~~~~~~~~~ hwndClient = GetParent (hwnd) hwndFrame = GetParent (hwndClient) 'Create controls for this window szClassName = "Static" hLblName1 = CreateWindowEx(0,szClassName,"Name of Client",%WS_CHILD OR %WS_VISIBLE,20,40,125,15,hwnd,1001,hInst,BYVAL 0&) hFont = GetStockObject(%ANSI_FIXED_FONT) SendMessage hLblName1, %WM_SETFONT, hFont, 0 szClassName = "Edit" hTxtName1 = CreateWindowEx(%WS_EX_CLIENTEDGE,szClassName,"",%ES_LEFT OR %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP,170,40,155,18,hwnd,1002,hInst,BYVAL 0&) hFont = GetStockObject(%ANSI_FIXED_FONT) SendMessage hTxtName1, %WM_SETFONT, hFont, 0 szClassName = "Static" hLblName2 = CreateWindowEx(0,szClassName,"Address",%WS_CHILD OR %WS_VISIBLE,20,60,125,15,hwnd,1003,hInst,BYVAL 0&) hFont = GetStockObject(%ANSI_FIXED_FONT) SendMessage hLblName2, %WM_SETFONT, hFont, 0 szClassName = "Edit" hTxtName2 = CreateWindowEx(%WS_EX_CLIENTEDGE,szClassName,"",%ES_LEFT OR %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP,170,60,155,18,hwnd,1004,hInst,BYVAL 0&) hFont = GetStockObject(%ANSI_FIXED_FONT) SendMessage hTxtName2, %WM_SETFONT, hFont, 0 FUNCTION = 0 CASE %WM_CTLCOLORBTN, %WM_CTLCOLOREDIT, %WM_CTLCOLORLISTBOX, %WM_CTLCOLORSTATIC IF lParam = GetDlgItem(hwnd,1001) THEN SetBkColor wParam,RGB(204,143,230) FUNCTION = GetStockObject(%NULL_BRUSH) EXIT FUNCTION END IF IF lParam = GetDlgItem(hwnd,1002) THEN SetTextColor wParam,%BLUE FUNCTION = GetStockObject(%WHITE_BRUSH) EXIT FUNCTION END IF IF lParam = GetDlgItem(hwnd,1003) THEN SetBkColor wParam,RGB(204,143,230) FUNCTION = GetStockObject(%NULL_BRUSH) EXIT FUNCTION END IF IF lParam = GetDlgItem(hwnd,1004) THEN SetTextColor wParam,%BLUE FUNCTION = GetStockObject(%WHITE_BRUSH) EXIT FUNCTION END IF CASE %WM_COMMAND SELECT CASE GetDlgCtrlId(lParam) CASE 1002 SELECT CASE HIWRD(wParam) CASE %EN_SETFOCUS SetWindowText hwnd,"Hello there!" CASE %EN_KILLFOCUS SetWindowText hwnd,"Goodbye" END SELECT END SELECT CASE %WM_MDIACTIVATE ' Set the Hello menu if gaining focus ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IF lParam = hwnd THEN CALL SendMessage (hwndClient, %WM_MDISETMENU,_ hMenuData, hMenuDataWindow) END IF ' Check or uncheck menu item ' ~~~~~~~~~~~~~~~~~~~~~~~~~~ ' lpHelloData = GetWindowLong (hwnd, 0) ' CALL CheckMenuItem (hMenuHello, @lpHelloData.iColor,_ ' IAssign(lParam = hwnd, %MF_CHECKED, %MF_UNCHECKED)) ' Set the Init menu if losing focus ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IF lParam <> hwnd THEN CALL SendMessage (hwndClient, %WM_MDISETMENU, hMenuInit,_ hMenuInitWindow) END IF CALL DrawMenuBar (hwndFrame) FUNCTION = 0 CASE %WM_QUERYENDSESSION, %WM_CLOSE 'Control get TEXT hwnd,1002 to sTxt GetWindowText GetDlgItem(hwnd,1002),Txt,%MAX_PATH sTxt = TRIM$(Txt) IF %IDOK <> MessageBox (hwnd, "OK to close Data window? " + TRIM$(stxt) , "Hello",_ %MB_ICONQUESTION OR %MB_OKCANCEL) THEN FUNCTION = 0 ELSE FUNCTION = DefMDIChildProc (hwnd, iMsg, wParam, lParam) END IF CASE %WM_DESTROY ' lpHelloData = GetWindowLong (hwnd, 0) ' CALL HeapFree (GetProcessHeap(), 0, lpHelloData) FUNCTION = 0 CASE ELSE FUNCTION = DefMDIChildProc (hwnd, iMsg, wParam, lParam) END SELECT END FUNCTION FUNCTION IAssign (BYVAL iCont AS LONG, _ BYVAL value1 AS LONG, BYVAL value2 AS LONG) AS LONG IF iCont THEN FUNCTION = value1 ELSE FUNCTION = value2 END IF END FUNCTION ' --------------------------------------------------------------------- FUNCTION RndInt (x AS LONG) AS LONG RndInt = INT(RND * x) + 1 END FUNCTION ' -------------------------------------------------------------------------- ' NOTES: ' ' ' ------------------------------------------------------------------------
Code:
/*----------------------- MDIDEMO.H header file -----------------------*/ #define EXPORT __declspec (dllexport) #define INIT_MENU_POS 0 #define DATA_MENU_POS 3 #define HELLO_MENU_POS 2 #define RECT_MENU_POS 1 #define IDM_NEWHELLO 10 #define IDM_NEWRECT 11 #define IDM_NEWDATA 12 #define IDM_CLOSE 13 #define IDM_EXIT 14 #define IDM_BLACK 20 #define IDM_RED 21 #define IDM_GREEN 22 #define IDM_BLUE 23 #define IDM_WHITE 24 #define IDM_TILE 30 #define IDM_CASCADE 31 #define IDM_ARRANGE 32 #define IDM_CLOSEALL 33 #define IDM_FIRSTCHILD 100
Code:
/*---------------------------- MDIDEMO.RC resource script ----------------------------*/ #include <resource.h> #include "mdidemo.h" MdiMenuInit MENU { POPUP "&File" { MENUITEM "New &Hello", IDM_NEWHELLO MENUITEM "New &Rectangles", IDM_NEWRECT MENUITEM "New Data", IDM_NEWDATA MENUITEM SEPARATOR MENUITEM "E&xit", IDM_EXIT } } MdiMenuHello MENU { POPUP "&File" { MENUITEM "New &Hello", IDM_NEWHELLO MENUITEM "New &Rectangles", IDM_NEWRECT MENUITEM "New Data", IDM_NEWDATA MENUITEM "&Close", IDM_CLOSE MENUITEM SEPARATOR MENUITEM "E&xit", IDM_EXIT } POPUP "&Color" { MENUITEM "&Black", IDM_BLACK MENUITEM "&Red", IDM_RED MENUITEM "&Green", IDM_GREEN MENUITEM "B&lue", IDM_BLUE MENUITEM "&White", IDM_WHITE } POPUP "&Window" { MENUITEM "&Cascade\tShift+F5", IDM_CASCADE MENUITEM "&Tile\tShift+F4", IDM_TILE MENUITEM "Arrange &Icons", IDM_ARRANGE MENUITEM "Close &All", IDM_CLOSEALL } } MdiMenuRect MENU { POPUP "&File" { MENUITEM "New &Hello", IDM_NEWHELLO MENUITEM "New &Rectangles", IDM_NEWRECT MENUITEM "New Data", IDM_NEWDATA MENUITEM "&Close", IDM_CLOSE MENUITEM SEPARATOR MENUITEM "E&xit", IDM_EXIT } POPUP "&Window" { MENUITEM "&Cascade\tShift+F5", IDM_CASCADE MENUITEM "&Tile\tShift+F4", IDM_TILE MENUITEM "Arrange &Icons", IDM_ARRANGE MENUITEM "Close &All", IDM_CLOSEALL } } MdiMenuData MENU { POPUP "&File" { MENUITEM "New &Hello", IDM_NEWHELLO MENUITEM "New &Rectangles", IDM_NEWRECT MENUITEM "New Data", IDM_NEWDATA MENUITEM "&Close", IDM_CLOSE MENUITEM SEPARATOR MENUITEM "E&xit", IDM_EXIT } POPUP "&Window" { MENUITEM "&Cascade\tShift+F5", IDM_CASCADE MENUITEM "&Tile\tShift+F4", IDM_TILE MENUITEM "Arrange &Icons", IDM_ARRANGE MENUITEM "Close &All", IDM_CLOSEALL } } MdiAccel ACCELERATORS { VK_F5, IDM_CASCADE, VIRTKEY, SHIFT VK_F4, IDM_TILE, VIRTKEY, SHIFT }
Code:
' ----------------------- ' MDIDEMO.H header file ' ----------------------- ' #define EXPORT __declspec (dllexport) %INIT_MENU_POS = 0 %DATA_MENU_POS = 3 %HELLO_MENU_POS = 2 %RECT_MENU_POS = 1 %IDM_NEWHELLO = 10 %IDM_NEWRECT = 11 %IDM_NEWDATA = 12 %IDM_CLOSE = 13 %IDM_EXIT = 14 %IDM_BLACK = 20 %IDM_RED = 21 %IDM_GREEN = 22 %IDM_BLUE = 23 %IDM_WHITE = 24 %IDM_TILE = 30 %IDM_CASCADE = 31 %IDM_ARRANGE = 32 %IDM_CLOSEALL = 33 %IDM_FIRSTCHILD = 100
Bob Mechler
Comment