Announcement

Collapse
No announcement yet.

Petzold's MDIDEMO and editbox navigation

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Petzold's MDIDEMO and editbox navigation

    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:
    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
         }
    MDIDEMO.INC 'seems to just hold the MDIDEMO.H info
    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
    Thanks,

    Bob Mechler
    Last edited by BOB MECHLER; 28 Jun 2008, 09:55 PM. Reason: Added rest of code to compile

  • #2
    Editbox navigation in a window

    Hello Bob

    Explore sub classing the edit fields in a window and trap the TAB, SHIFT and ENTER keys. When this is done, try the API call to GetNextDlgItem. This can be done but straight dialogs are much simpler for data entry.

    David

    Comment


    • #3
      Subclassing and/or Superclassing the controls would then probably work.

      I've written a Superclassed editbox based on Semen's fine example that when several are on screen I can use up/down arrows, tab, shift tab, enter all to move between fields.

      Can an sdk dialogbox also be a mdi child? It seems from the api help that the dialogbox is more for this type of thing.

      One thing I like about where the shown code goes is that I can open up several of the same windows and the text in the controls remains discreet. This would allow for an operator to have several accounts open using the same window with multiple instances and with proper care deal with them.

      It was quite impressive to open 4 of the 'New Rectangles' windows and Tile them and they all run independently.

      In a financial app this could lend itself to watching a real time feed, be processing the days transactions, running a report and maintaining a customer's account all at the same time. We already have people setting two or three monitors side by side just to multitask. With the larger monitors available it might be worth pursuing.

      Bob Mechler

      Comment


      • #4
        Add style WS_EX_CONTROLPARENT to the MDI child window. That will enable the tab keys as 'focus-shifters' without subclassing.

        To enable arrows for same you will have to subclass.
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          The following worked using subclass in a box to tab between controls in a mdi child window but what I normally use;
          SetFocus GetNextDlgTabItem(getparent(phwnd),getfocus,0)
          did not work and gave a gpf error. I'd rather use the SetFocus method so I don't have to determine the control id and then set the next jump.

          Code:
          FUNCTION EditProc(BYVAL phWnd AS DWORD, BYVAL pdMsg AS DWORD, BYVAL pWParam AS DWORD, BYVAL pLParam AS LONG) AS LONG
            SELECT CASE AS LONG pdMsg
              CASE %WM_KEYDOWN
                SELECT CASE pWParam
          	CASE %VK_TAB
                    SELECT CASE getdlgctrlid(phwnd)
                      CASE 1002
                        control set focus getparent(phwnd),1004
                      CASE 1004
                        control set focus getparent(phwnd),1002              
                     END SELECT  
                     EXIT FUNCTION
                 END SELECT
              
             END SELECT
          		mSC_OrgProc
          
          END FUNCTION
          I also couldn't figure out where to put the %WS_EX_CONTROLPARENT. I tried changing every CreateWindow to CreateWindowEx and had no luck.

          Bob Mechler
          Last edited by BOB MECHLER; 29 Jun 2008, 04:42 PM.

          Comment


          • #6
            I assume in your createWindowEx for the MDI children you set the ExStyle (param 1) to include WS_EX_CONTROLPARENT??? I don't know that you can add that style after creation.

            But.... assuming you want to go the subclass route, you can avoid the hard-coded Ids on the tab keys using....

            Code:
            FUNCTION SubClassProc_FindEdit (BYVAL hWnd AS LONG, BYVAL wMSG AS LONG, BYVAL wPARAM AS LONG, BYVAL lParam AS LONG) AS LONG
            
             LOCAL  szPropertyName  AS ASCIIZ * 16
             LOCAL  hCtrl AS LONG
            
                 ' make this static so we only have to look it up once
                 STATIC oldwndProc AS LONG
                 IF ISFALSE oldWndProc THEN
                     szPropertyName = $PROP_OLD_WNDPROC
                     OldWndProc =  Getprop (hWnd, szPropertyName)  ' we stored address as the handle value of property
            
                 END IF
            
                 SELECT CASE AS LONG wMSg
                     ' we want the enter key, and want to make that into a "find next" action
                     CASE %WM_GETDLGCODE
                         FUNCTION =  %DLGC_WANTALLKEYS     ' With DLCG_WANTCHARS all regular keys work but no WM-CHAR message
                         EXIT FUNCTION
            
                    CASE  %WM_CHAR                      '"An application should return zero if it processes this message. "
                        IF wParam = %VK_TAB THEN
                             ' standard TAB behavior
                               [b]SetFocus       GetnextDlgTabItem(GetParent(hWnd), hWnd, (GetKeyState(%VK_SHIFT) < 0))[/b]
            ' ****NOTE: Assumes GetKeyState() in your Win32API.INC is returning a LONG not a DWORD ******
                               FUNCTION = 0
                               EXIT FUNCTION
                        END IF
            
                   END SELECT
                   ' if message nothandled (proc exited), call default handler
                   FUNCTION = CallWindowProc (OldWndProc, hWnd, wMsg, wParam,lparam)
            
            END FUNCTION
            .. or maybe you'd just like to eschew the use of DDT commands ("control set focus") on non-DDT windows in an unsupported location (procedure other than that named in a DIALOG SHOW or CONTROL ADD statement).


            MCM
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              Code for the MDI Frame
              Code:
                hwndFrame = CreateWindow (szFrameClass, "MDI Demonstration",_
                                          %WS_OVERLAPPEDWINDOW OR %WS_CLIPCHILDREN,_
                                          %CW_USEDEFAULT, %CW_USEDEFAULT,_
                                          %CW_USEDEFAULT, %CW_USEDEFAULT,_
                                          %NULL, hMenuInit, hCurrInstance, %NULL)
              Code for the MDI Child

              From your post Michael I'm assuming the %WS_EX_CONTROLPARENT was supposed to go in the following by changing from CreateWindow to CreateWindowEx
              Code:
                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))
              to
              Code:
                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 = CreateWindowex (%WS_EX_CONTROLPARENT,"MDICLIENT", BYVAL %NULL,_
                                               %WS_CHILD OR %WS_CLIPCHILDREN OR %WS_VISIBLE,_
                                               0, 0, 0, 0, hwnd, 1, hInst,_
                                               VARPTR(clientCreate))
              But it wouldn't compile saying in the VARPTR(clientCreate) that a variable was expected. Never could spot the error which is why I coded it the other way. Without the %WS_EX_CONTROLPARENT I guess the SetFocus GetNextDlgTabItem caused the GPF.

              There are only two CreateWindow functions that create the MDIFrame and all the MdiChild Windows. I tried placing the %WS_EX_CONTROLPARENT in either place and no luck.

              The CLIENTCREATESTRUCT from the doc must be used to point to the first MDI child created from the WIn32api instructions.

              Chris Boss had a mixed style MDI with DDT but it would not allowing tabbing either.

              So you're telling me to put a style where it won't compile.

              Bob Mechler

              Comment


              • #8
                Ok, I've stripped the subclassing out just to try and get the WS_EX_CONTROLPARENT rightly applied. The following is what I believe you are saying I should do and it doesn't compile. The only substantive change was to the MDIChild create CreateWindow to a CreateWindowEx with the extended style as param 1. It compiles as CreateWindow says it's expecting a variable with CreateWindowEx. The clientCreate as CLIENTCREATESTRUCT seems to be required when creating the MDI child windows but that is where it is complaining.

                Hope by taking it a step at a time I can get the information that will it allow it to compile.

                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"
                
                
                '      MACRO mSC_Set(phDlg, phCtl, pProc)
                '      		SetWindowLong GetDlgItem(phDlg, phCtl), %GWL_USERDATA, _
                '      				SetWindowLong(GetDlgItem(phDlg, phCtl), %GWL_WNDPROC, CODEPTR(pProc))
                '      END MACRO
                '      MACRO mSC_Kill(phCtl)
                '      		SetWindowLong(GetDlgItem(hwnd, phCtl), %GWL_WNDPROC, _
                '      				GetWindowLong(hwnd, %GWL_USERDATA))
                '      END MACRO
                '      MACRO mSC_OrgProc
                '      		FUNCTION = CallWindowProc(GetWindowLong(phWnd, %GWL_USERDATA), phWnd, pdMsg, pWParam, pLParam)
                '      END MACRO    
                ' 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
                
                ' 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 = CreateWindowEx (%WS_EX_CONTROLPARENT,"MDICLIENT", BYVAL %NULL,_
                                                 %WS_CHILD OR %WS_CLIPCHILDREN OR %WS_VISIBLE,_
                                                 0, 0, 0, 0, hwnd, 1, hInst,_
                                                 VARPTR(clientCreate))       '<----------------Compile fails here
                      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 EditProc(BYVAL phWnd AS DWORD, BYVAL pdMsg AS DWORD, BYVAL pWParam AS DWORD, BYVAL pLParam AS LONG) AS LONG
                '		SELECT CASE AS LONG pdMsg
                '		  CASE %WM_KEYDOWN
                '		  SELECT CASE pWParam
                '		    CASE %VK_TAB
                '          'SetFocus GetNextDlgTabItem(, phWnd, 0)
                '          SELECT CASE getdlgctrlid(phwnd)
                '            CASE 1002
                '              control set focus getparent(phwnd),1004
                '            CASE 1004
                '              control set focus getparent(phwnd),1002              
                '            'SetFocus GetNextDlgTabItem(getparent(phwnd),getfocus(),0)
                '          END SELECT  
                '          EXIT FUNCTION
                '		  END SELECT
                '    
                '    END SELECT
                '		mSC_OrgProc
                '
                'END FUNCTION
                'FUNCTION SubClassProc_FindEdit (BYVAL hWnd AS LONG, BYVAL wMSG AS LONG, BYVAL wPARAM AS LONG, BYVAL lParam AS LONG) AS LONG
                '  LOCAL  szPropertyName  AS ASCIIZ * 16
                '  LOCAL  hCtrl AS LONG     
                '  ' make this static so we only have to look it up once     
                '  STATIC oldwndProc AS LONG
                '  IF ISFALSE oldWndProc THEN
                '    's'zPropertyName = $PROP_OLD_WNDPROC
                '    OldWndProc = Getprop(hWnd, szPropertyName) 'we stored address as the handle value of property
                '  END IF
                '  
                '  SELECT CASE AS LONG wMsg
                '    ' we want the enter key, and want to make that into a "find next" action
                '    CASE %WM_GETDLGCODE
                '      FUNCTION = %DLGC_WANTALLKEYS '' With DLCG_WANTCHARS all regular keys work but no WM-CHAR message  
                '      EXIT FUNCTION
                '    CASE %WM_CHAR
                '      IF wParam = %VK_TAB THEN
                '        'standard behaviour
                '        SetFocus GetNextDlgTabItem(GetParent(hwnd),hwnd,(GetKeyState(%VK_SHIFT) < 0))
                '        ' ****NOTE: Assumes GetKeyState() in your Win32API.INC is returning a LONG not a DWORD ******
                '        FUNCTION = 0
                '        EXIT FUNCTION
                '      END IF
                '      
                '    END SELECT
                '    ' if message not handled (proc exited), call default handler
                '    'mSC_OrgProc
                '    FUNCTION= CallWindowProc(OldWndProc,hWnd,wMsg,wParam,lParam)    
                'END FUNCTION
                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
                
                '     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 or %WS_EX_CONTROLPARENT,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
                '      mSC_Set(hwnd,1002,EditProc)
                
                
                      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 or %WS_EX_CONTROLPARENT,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
                '      mSC_Set(hwnd,1004,EditProc)
                
                      
                
                      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
                      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)
                '      msC_Kill(1002)
                '      msC_Kill(1004)
                      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

                Comment


                • #9
                  This variation would compile when I removed the VARPTR around clientCreate
                  but it would not tab between fields in the child window.

                  Code:
                        clientCreate.hWindowMenu  = hMenuInitWindow  'See PW95, 952
                        clientCreate.idFirstChild = %IDM_FIRSTCHILD  '
                  
                        hwndClient = CreateWindowEx (%WS_EX_CONTROLPARENT, _
                                            "MDICLIENT", BYVAL %NULL,_
                                             %WS_CHILD OR %WS_CLIPCHILDREN OR %WS_VISIBLE,_
                                              0, 0, 0, 0, hwnd, 1, hInst,_
                                              clientCreate)       '<----Compiles but doesn't tab

                  Comment


                  • #10
                    Deleted by Bob Mechler.
                    Point was already made earlier.
                    Last edited by BOB MECHLER; 29 Jun 2008, 09:43 PM.

                    Comment


                    • #11
                      Edwin Knoppert's code seems to work based on using CREATEWINDOWEX and %WS_EX_CONTROLPARENT when creating the child control. I added a second textbox and it worked fine. I guess I'll shelve dear old Petzold's example and go with Edwin's.

                      Still would like to know what was wrong with my last version of Petzold's with child window and textboxes!

                      Bob Mechler

                      Comment


                      • #12
                        Edwin is creating a dialog in the MDI child. I thought that might be a possibility although it seems unnecessary. What do I know, I just started looking at MDI yesterday.

                        Bob Mechler

                        Comment


                        • #13
                          I think I may have steered you wrong.

                          WS_EX_CONTROLPARENT works just fine in my apps, but those windows are created with CreateWindowEx, not with WM_MDICREATE.

                          Looking over the MDI doc this AM, I can't see how you can create an MDI child with that style. In my one remaining MDI application I subclass all the controls to get the standard keyboard interface.

                          You could try adding the style in the WM_CREATE message of each MDI child window with:

                          Code:
                          LastExStyle = SetWindowLong (hWnd, %gwl_exstyle, %WS_EX_CONTROLPARENT)

                          Unfortunately testing for the success of this call will be a bit tricky because the value of LastExStyle will have been zero. From the SDK:

                          If the previous value of the specified 32-bit integer is zero, and the function succeeds, the return value is zero, but the function does not clear the last error information. This makes it difficult to determine success or failure. To deal with this, you should clear the last error information by calling SetLastError(0) before calling SetWindowLong. Then, function failure will be indicated by a return value of zero and a GetLastError result that is nonzero.
                          or..

                          Code:
                          SetLastError    %NULL
                          iret          = SetWindowLong (hWnd, %GWL_exstyle, %WS_EX_CONTROLPARENT)
                          LE            = GetLastError ()
                          
                          IF (ISFALSE iret) AND (ISTRUE LE) THEN 
                             it failed. 
                          END IF

                          MCM
                          Michael Mattias
                          Tal Systems (retired)
                          Port Washington WI USA
                          [email protected]
                          http://www.talsystems.com

                          Comment


                          • #14
                            Snce I may have sent you off on a wild goose chase, I did a little extra research and found this:
                            Creating a Child Window
                            To create an MDI child window, an application can either call the CreateMDIWindow function or send an WM_MDICREATE message to the MDI client window. (The application can use the CreateWindowEx function with the WS_EX_MDICHILD style to create MDI child windows.)
                            So, sure looks like you could try CreateWindowEx using an ExStyle of (WS_EX_MDICHILD OR WS_EX_CONTROLPARENT) to create your child windows.

                            (Or I guess any of the WS_EX_xxx styles).

                            MCM
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              deleted by Bob Mechler
                              Last edited by BOB MECHLER; 30 Jun 2008, 09:28 AM.

                              Comment


                              • #16
                                Subclassing is probably the best way to go but these mods to the original code seem to work..
                                Code:
                                 
                                        CASE %IDM_NEWDATA                  'Create a Rect child window
                                '..         
                                          hwndChild = SendMessage (hwndClient, %WM_MDICREATE, 0,_
                                                                               VARPTR(mdiCreate))
                                          SetWindowLong (hWndChild, %GWL_EXSTYLE, GetWindowLong(hWnd, %GWL_EXSTYLE) OR %WS_EX_CONTROLPARENT)
                                as long as you also modify the message loop something like..
                                Code:
                                  LOCAL hwndChild AS LONG 
                                '..
                                ' Main message loop of program
                                ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                  WHILE GetMessage(msg, %NULL, 0, 0)
                                    IF TranslateMDISysAccel(hWndClient, msg) OR _
                                       TranslateAccelerator(hWndFrame, hAccel, msg) THEN
                                      'Skip
                                    ELSE 
                                      hwndChild = GetWindow (hwndClient, %GW_CHILD)
                                      IF ISFALSE hWndChild OR ISFALSE(IsDialogMessage(hWndChild, Msg)) THEN              '
                                        CALL TranslateMessage (msg)              'translates some keyboard messages
                                        CALL DispatchMessage  (msg)              'sends a message to a window procedure
                                      END IF
                                    END IF
                                  WEND
                                Last edited by Dave Biggs; 1 Jul 2008, 08:50 AM. Reason: Clarify position of SetWindowLong..
                                Rgds, Dave

                                Comment


                                • #17
                                  Code:
                                            hwndChild = SendMessage (hwndClient, %WM_MDICREATE, 0,_
                                                                                 VARPTR(mdiCreate)) 
                                            '~~~~~~~~~~~
                                            SetWindowLong (hwndChild,%GWL_EXSTYLE, GetWindowLong(hWnd,%GWL_EXSTYLE) OR %WS_EX_CONTROLPARENT)
                                            '~~~~~~~~~~~
                                  and
                                  Code:
                                  '~~~~~~~~~~~~~~~~~~~~
                                  ' Main message loop of program
                                  ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                    WHILE GetMessage(msg, %NULL, 0, 0)
                                      IF TranslateMDISysAccel(hWndClient, msg) OR _
                                         TranslateAccelerator(hWndFrame, hAccel, msg) THEN
                                        'Skip
                                      ELSE 
                                      '~~~~~~~~~~~~~~~~~~~~~~~~~~
                                        hwndChild = GetWindow (hwndClient, %GW_CHILD)
                                        IF ISFALSE hWndChild OR ISFALSE(IsDialogMessage(hWndChild, Msg)) THEN
                                      '~~~~~~~~~~~~~~~~~~~~~~~~~~  
                                          CALL TranslateMessage (msg)              'translates some keyboard messages
                                          CALL DispatchMessage  (msg)              'sends a message to a window procedure
                                      '~~~~~~~~~~~~~~
                                        END IF
                                      '~~~~~~~~~~~~~~  
                                      END IF
                                    WEND
                                  On my system still GPF's
                                  Subclassing works fine though.

                                  Bob Mechler

                                  Comment


                                  • #18
                                    Code:
                                     ELSE 
                                          hwndChild = GetWindow (hwndClient, %GW_CHILD)
                                          IF ISFALSE hWndChild OR ISFALSE(IsDialogMessage(hWndChild, Msg)) THEN
                                    ???

                                    That won't send messages to the MDI client window when GetWindow DOES find the first (in th Z-order) MDI child. (They'll go in the bit bucket).
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment


                                    • #19
                                      Bob
                                      On my system still GPF's
                                      Pasting into the code posted in message #1 works OK on my systems - WinXP Pro and Home.
                                      Compiled with PB/Win 8.04.

                                      MCM
                                      That won't send messages to the MDI client window when GetWindow DOES find the first (in th Z-order) MDI child. (They'll go in the bit bucket).
                                      That's right. We don't want the messages sent to the MDI Client when there is a Child window.
                                      It seems that the Client 'eats' them - at least they don't get to the Child window which is the one
                                      that has the %WS_EX_CONTROLPARENT style (where we want to navigate using the TAB key).

                                      (See the remarks in the SDK docs for IsDialogMessage).

                                      I tried this route after reading Lance's post here..
                                      http://www.powerbasic.com/support/fo...ML/005904.html and it seems to work


                                      Mind you I don't totally have my head around this so that's why I said,
                                      "modify the message loop something like.."
                                      Rgds, Dave

                                      Comment


                                      • #20
                                        >We don't want the messages sent to the MDI Client when there is a Child window

                                        We don't?

                                        Um, what if the message is FOR the MDI client? eg, WM_MDIGETACTIVE? (which is probably what you want above anyway instead of GetWindow(%GW_CHILD). Or WM_MDISETMENU?

                                        (The use of IsDialogMessage() is imaginative, but above code never tests that for the MDI client)

                                        MCM
                                        Michael Mattias
                                        Tal Systems (retired)
                                        Port Washington WI USA
                                        [email protected]
                                        http://www.talsystems.com

                                        Comment

                                        Working...
                                        X