Announcement

Collapse
No announcement yet.

Invalid Memory Address

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

    Invalid Memory Address

    Using the code below to demonstrate my problem, does not demonstrate my problem (surprise).
    Code:
    #PBFORMS CREATED V1.51
    '------------------------------------------------------------------------------
    ' The first line in this file is a PB/Forms metastatement.
    ' It should ALWAYS be the first line of the file. Other
    ' PB/Forms metastatements are placed at the beginning and
    ' end of "Named Blocks" of code that should be edited
    ' with PBForms only. Do not manually edit or delete these
    ' metastatements or PB/Forms will not be able to reread
    ' the file correctly.  See the PB/Forms documentation for
    ' more information.
    ' Named blocks begin like this:    #PBFORMS BEGIN ...
    ' Named blocks end like this:      #PBFORMS END ...
    ' Other PB/Forms metastatements such as:
    '     #PBFORMS DECLARATIONS
    ' are used by PB/Forms to insert additional code.
    ' Feel free to make changes anywhere else in the file.
    '------------------------------------------------------------------------------
    
    #COMPILE EXE
    #DIM ALL
    
    '------------------------------------------------------------------------------
    '   ** Includes **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN INCLUDES
    #IF NOT %DEF(%WINAPI)
        #INCLUDE "WIN32API.INC"
    #ENDIF
    #PBFORMS END INCLUDES
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Constants **
    '------------------------------------------------------------------------------
    #PBFORMS BEGIN CONSTANTS
    %IDD_DIALOG1 = 101
    #PBFORMS END CONSTANTS
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Declarations **
    '------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
    #PBFORMS DECLARATIONS
    GLOBAL HwndMain AS LONG
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Main Application Entry Point **
    '------------------------------------------------------------------------------
    FUNCTION PBMAIN()
        ShowDIALOG1 %HWND_DESKTOP
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** CallBacks **
    '------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
    
        SELECT CASE AS LONG CBMSG
            CASE %WM_INITDIALOG
                ' Initialization handler
    
            CASE %WM_NCACTIVATE
                STATIC hWndSaveFocus AS DWORD
                IF ISFALSE CBWPARAM THEN
                    ' Save control focus
                    hWndSaveFocus = GetFocus()
                ELSEIF hWndSaveFocus THEN
                    ' Restore control focus
                    SetFocus(hWndSaveFocus)
                    hWndSaveFocus = 0
                END IF
    CASE %WM_SIZE
              LOCAL HwndMainRect AS RECT
              LOCAL x AS LONG
              LOCAL y AS LONG
              LOCAL xx AS LONG
              LOCAL yy AS LONG
    '*** Get Toolbar and statusbar height
              GetWindowRect HwndMain, HwndMainRect
    MSGBOX STR$(HwndMainRect.nLeft) + "," + STR$(HwndMainRect.nBottom)
              DIALOG PIXELS HwndMain, HwndMainRect.nLeft, HwndMainRect.nBottom TO UNITS HwndMainRect.nLeft, HwndMainRect.nBottom
    MSGBOX STR$(HwndMainRect.nLeft) + "," + STR$(HwndMainRect.nBottom)
    'MSGBOX STR$(xx) + "," + STR$(yy)
         
            CASE %WM_COMMAND
                ' Process control notifications
                SELECT CASE AS LONG CBCTL
    
                END SELECT
        END SELECT
    END FUNCTION
    '------------------------------------------------------------------------------
    
    '------------------------------------------------------------------------------
    '   ** Dialogs **
    '------------------------------------------------------------------------------
    FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
        LOCAL lRslt AS LONG
    
    #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
        LOCAL hDlg  AS DWORD
    
        DIALOG NEW hParent, "Dialog1", 70, 70, 201, 121, %WS_POPUP OR %WS_BORDER _
            OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
            %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
            %WS_CLIPCHILDREN OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _
            %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT _
            OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
    #PBFORMS END DIALOG
    HwndMain = hDlg
        DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
    
    #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
    #PBFORMS END CLEANUP
    
        FUNCTION = lRslt
    END FUNCTION
    '------------------------------------------------------------------------------
    But using the same code (%WM_SIZE) section in my wicked huge program (hence "Code Not SHOWN") causes a "Invalid Memory Address GPF"

    So I started looking at what was different, and what is different is my Main program is a MDI Dialog of sorts, so I grabbed "PbNote2" and tried the same test.

    Code:
    '==============================================================================
    '
    '   PBNOTE2.BAS example for PowerBASIC For Windows
    '   Copyright (c) 1997-2008 PowerBASIC, Inc.
    '   All Rights Reserved.
    '
    '   MDI text editor - based on the PBNote sample, but menu, string table and
    '   accelator code, etc, has been lifted out from resource into this code,
    '   and a complete PrintDocument procedure has been added.
    '
    '   Note:  Windows 95 "thunks down" to the 16-bit GDI for edit boxes, so
    '          edit boxes are limited to 64k in Windows 95.  Edit controls in
    '          Windows NT have a higher limit, here we set 1,048,576 bytes.
    '
    '
    '==============================================================================
    
    '------------------------------------------------------------------------------
    ' Initial Declares - first eliminate unnecessary functions in COMMCTRL.INC
    '------------------------------------------------------------------------------
    %NOANIMATE         = 1  ' Animate control
    %NOBUTTON          = 1  ' Button
    %NOCOMBO           = 1  ' Combo box
    %NOCOMBOEX         = 1  ' ComboBoxEx
    %NODATETIMEPICK    = 1  ' Date/time picker
    %NODRAGLIST        = 1  ' Drag list control
    %NOEDIT            = 1  ' Edit control
    %NOFLATSBAPIS      = 1  ' Flat scroll bar
    %NOHEADER          = 1  ' Header control
    %NOHOTKEY          = 1  ' HotKey control
    %NOIMAGELIST       = 1  ' Image APIs
    %NOIPADDRESS       = 1  ' IP Address edit control
    %NOLIST            = 1  ' List box control
    %NOLISTVIEW        = 1  ' ListView control
    %NOMENUHELP        = 1  ' Menu help
    %NOMONTHCAL        = 1  ' MonthCal
    %NOMUI             = 1  ' MUI
    %NONATIVEFONTCTL   = 1  ' Native Font control
    %NOPAGESCROLLER    = 1  ' Pager
    %NOPROGRESS        = 1  ' Progress control
    %NOREBAR           = 1  ' Rebar control
    ' %NOSTATUSBAR     = 1  ' Status bar
    %NOTABCONTROL      = 1  ' Tab control
    ' %NOTOOLBAR       = 1  ' Tool bar
    ' %NOTOOLTIPS      = 1  ' Tool tips
    %NOTRACKBAR        = 1  ' Track bar
    %NOTRACKMOUSEEVENT = 1  ' Track Mouse Event
    %NOTREEVIEW        = 1  ' TreeView
    %NOUPDOWN          = 1  ' Up Down arrow control
    '------------------------------------------------------------------------------
    %USEMACROS         = 1  ' Use Macros in include files, where possible
    
    '------------------------------------------------------------------------------
    #COMPILER PBWIN 9
    #COMPILE EXE
    '#RESOURCE "PBNOTE2.PBR"
    #DIM ALL
    
    '------------------------------------------------------------------------------
    #INCLUDE "Win32API.inc"  ' Win32 API declares and equates, etc.
    #INCLUDE "CommCtrl.inc"  ' Common control declares and equates, etc.
    #INCLUDE "InitCtrl.inc"  ' improved initiation for Common controls
    #INCLUDE "ComDlg32.inc"  ' Common dialog declares and equates, etc.
    #INCLUDE "MDI32.inc"     ' wrappers for some MDI-related calls
    
    '------------------------------------------------------------------------------
    $PROGRAMCLASSNAME = "PBNote2"        ' Main window class
    $NOTEPADCLASSNAME = "PBNOTE32"       ' MDI child class
    $INIFILENAME      = "PBNote2.ini"    ' configuration file
    $HELPFILE         = "PBWin.hlp"      ' help file (alter name as necessary)
    
    '------------------------------------------------------------------------------
    %ID_TOOLBAR           = %WM_USER      + 1024&  ' toolbar
    %ID_STATUSBAR         = %WM_USER      + 1025&  ' statusbar
    %IDC_EDIT             = %WM_USER      + 1026&  ' edit control
    
    ' FILE
    %IDM_NEW              = %WM_USER      + 2000&  ' New File
    %IDM_OPEN             = %WM_USER      + 2001&  ' Open File
    %IDM_SAVE             = %WM_USER      + 2005&  ' Save
    %IDM_SAVEAS           = %WM_USER      + 2006&  ' Save As
    %IDM_PRINT            = %WM_USER      + 2007&  ' Print
    %IDM_EXIT             = %WM_USER      + 2009&  ' Exit
    %IDM_RECENT1          = %WM_USER      + 2010&  ' Recently opened file 1
    %IDM_RECENT2          = %WM_USER      + 2011&  ' Recently opened file 2
    %IDM_RECENT3          = %WM_USER      + 2012&  ' Recently opened file 3
    %IDM_RECENT4          = %WM_USER      + 2013&  ' Recently opened file 4
    %IDM_RECENT5          = %WM_USER      + 2014&  ' Recently opened file 5
    %IDM_RECENT6          = %WM_USER      + 2015&  ' Recently opened file 6
    %IDM_RECENT7          = %WM_USER      + 2016&  ' Recently opened file 7
    %IDM_RECENT8          = %WM_USER      + 2017&  ' Recently opened file 8
    
    ' EDIT
    %IDM_UNDO             = %WM_USER      + 2030&   ' Undo
    %IDM_CUT              = %WM_USER      + 2032&   ' Cut
    %IDM_COPY             = %WM_USER      + 2033&   ' Copy
    %IDM_PASTE            = %WM_USER      + 2034&   ' Paste
    %IDM_DELETE           = %WM_USER      + 2035&   ' Delete
    %IDM_SELALL           = %WM_USER      + 2036&   ' Select all
    
    ' WINDOW
    %IDM_CASCADE          = %WM_USER      + 2060&   ' Cascade windows
    %IDM_TILEH            = %WM_USER      + 2061&   ' Tile windows horizontally
    %IDM_TILEV            = %WM_USER      + 2062&   ' Tile windows vertically
    %IDM_ARRANGE          = %WM_USER      + 2065&   ' Arrange icons
    %IDM_CLOSE            = %WM_USER      + 2067&   ' Close all
    
    ' HELP
    %IDM_ABOUT            = %WM_USER      + 2086&   ' About box
    
    '------------------------------------------------------------------------------
    GLOBAL g_hInst        AS DWORD
    GLOBAL g_hMenu        AS DWORD
    GLOBAL g_hMenuEdit    AS DWORD
    GLOBAL g_hMenuFile    AS DWORD
    GLOBAL g_hMenuReopen  AS DWORD
    GLOBAL g_hMenuWindow  AS DWORD
    GLOBAL g_hStatus      AS DWORD
    GLOBAL g_hToolbar     AS DWORD
    GLOBAL g_hWndMain     AS DWORD
    GLOBAL g_hWndClient   AS DWORD
    GLOBAL g_fClosed      AS LONG
    GLOBAL g_FreezeMenu   AS LONG
    GLOBAL g_NewComCtl    AS CURRENCYX
    GLOBAL g_NewDocNum    AS LONG
    GLOBAL g_zIni         AS ASCIIZ * %MAX_PATH
    
    '------------------------------------------------------------------------------
    DECLARE FUNCTION MakeAccelerators() AS DWORD
    DECLARE FUNCTION MakeMenu  (BYVAL hWnd AS DWORD) AS DWORD
    DECLARE FUNCTION MakeToolBar (BYVAL hWnd AS DWORD) AS DWORD
    DECLARE FUNCTION FileExist (BYVAL sfName AS STRING) AS LONG
    DECLARE FUNCTION FileNam   (BYVAL Src AS STRING) AS STRING
    DECLARE FUNCTION FilePath  (BYVAL Src AS STRING) AS STRING
    DECLARE FUNCTION GetEdit () AS LONG
    DECLARE FUNCTION GetStringTable (BYVAL ID AS LONG) AS STRING
    DECLARE FUNCTION IsWin95() AS LONG
    DECLARE FUNCTION OpenThisFile (BYVAL fn AS STRING) AS DWORD
    '------------------------------------------------------------------------------
    DECLARE SUB GetRecentFiles
    DECLARE SUB HideButtons   (BYVAL HideState AS LONG)
    DECLARE SUB PrintDocument (BYVAL hEdit AS DWORD)
    DECLARE SUB SAVEFILE      (BYVAL Ask AS LONG)
    DECLARE SUB WriteRecentFiles (BYVAL OpenFName AS STRING)
    
    GLOBAL HwndMain AS LONG
    
    '==============================================================================
    FUNCTION WINMAIN (BYVAL hInstance     AS DWORD, _
                      BYVAL hPrevInstance AS DWORD, _
                      BYVAL lpCmdLine     AS ASCIIZ PTR, _
                      BYVAL iCmdShow      AS LONG) AS LONG
    '------------------------------------------------------------------------------
      ' Program entrance
      '----------------------------------------------------------------------------
    
      LOCAL hAccel       AS DWORD
      LOCAL Msg          AS TAGMSG
      LOCAL wce          AS WNDCLASSEX
      LOCAL szClassName  AS ASCIIZ * 80
    
      g_hInst = hInstance 'store module handle in global variable for later use
    
      GetModuleFileName g_hInst, g_zIni, %MAX_PATH          ' get path to program
      g_zIni = LEFT$(g_zIni, INSTR(-1, g_zIni, ANY "\/:"))  ' this is same as AppPath
      g_zIni = g_zIni & $INIFILENAME                        ' use AppPath for ini file
    
      '----------------------------------------------------------------------------
      ' Register Main Window Class
      szClassName       = $PROGRAMCLASSNAME
      wce.cbSize        = SIZEOF(wce)
      wce.STYLE         = %CS_HREDRAW OR %CS_VREDRAW
      wce.lpfnWndProc   = CODEPTR(WndProc)
      wce.cbClsExtra    = 0
      wce.cbWndExtra    = 0
      wce.hInstance     = g_hInst
      wce.hIcon         = LoadIcon(g_hInst, "APPICON")
      IF wce.hIcon = 0 THEN 'if no resource icon, give it a system icon..
         wce.hIcon = LoadIcon(0, BYVAL %IDI_APPLICATION)
      END IF
      wce.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)
      wce.hbrBackground = %NULL
      wce.lpszMenuName  = %NULL
      wce.lpszClassName = VARPTR(szClassName)
      wce.hIconSm       = LoadIcon(g_hInst, BYVAL %IDI_APPLICATION)
    
      IF RegisterClassEx(wce) = 0 THEN
          RegisterClass BYVAL (VARPTR(wce) + 4)
      END IF
    
      '----------------------------------------------------------------------------
      ' Register Code Window Class
      szClassName       = $NOTEPADCLASSNAME
      wce.cbSize        = SIZEOF(wce)
      wce.STYLE         = %CS_DBLCLKS OR %CS_HREDRAW OR %CS_VREDRAW
      wce.lpfnWndProc   = CODEPTR(CodeProc)
      wce.cbClsExtra    = 0
      wce.cbWndExtra    = 4
      wce.hInstance     = g_hInst
      wce.hIcon         = LoadIcon(g_hInst, "NOTEICON")
      IF wce.hIcon = 0 THEN 'if no resource icon, give it a system icon..
         wce.hIcon = LoadIcon(0, BYVAL %IDI_APPLICATION)
      END IF
      wce.hCursor       = LoadCursor(%NULL, BYVAL %IDC_IBEAM)
      wce.hbrBackground = %NULL
      wce.lpszMenuName  = %NULL
      wce.lpszClassName = VARPTR(szClassName)
      wce.hIconSm       = LoadIcon(g_hInst, BYVAL %IDI_APPLICATION)
    
      IF ISFALSE(RegisterClassEx(wce)) THEN
          RegisterClass BYVAL (VARPTR(wce) + 4)
      END IF
    
      '----------------------------------------------------------------------------
      g_hMenu       = MakeMenu(g_hWndMain)              'main menu
      g_hMenuFile   = GetSubMenu(g_hMenu, 0)            'File menu
      g_hMenuReopen = GetSubMenu(g_hMenuFile, 2)        'Reopen files submenu
      g_hMenuEdit   = GetSubMenu(g_hMenu, 1)            'Edit menu
      g_hMenuWindow = GetSubMenu(g_hMenu, 2)            'Window menu
    
      '----------------------------------------------------------------------------
      ' Create main window using the registered class
      g_hWndMain = CreateWindow($PROGRAMCLASSNAME, _      ' Main window's class name
                                $PROGRAMCLASSNAME, _      ' Main window's initial caption
                                %WS_OVERLAPPEDWINDOW, _   ' window style
                                (GetSystemMetrics(%SM_CXSCREEN) - 640) / 2, _  ' initial x position
                                (GetSystemMetrics(%SM_CYSCREEN) - 480) / 2, _  ' initial y position
                                640, _                    ' initial x size
                                480, _                    ' initial y size
                                %NULL, _                  ' parent window handle
                                g_hMenu, _                ' window menu handle
                                g_hInst, _                ' program instance handle
                                BYVAL %NULL)              ' creation parameters
    
      '----------------------------------------------------------------------------
      hAccel = MakeAccelerators()
    
      GetRecentFiles    ' fill the Recent files menu (MRU) ..
      HideButtons %TRUE
    
      ShowWindow g_hWndMain, iCmdShow
      UpdateWindow g_hWndMain
    
    HwndMain = g_hWndMain
      '----------------------------------------------------------------------------
      ' Message handler loop
      WHILE GetMessage(Msg, BYVAL %NULL, 0, 0)
         IF TranslateMDISysAccel(g_hWndClient, Msg) = 0 THEN
            IF TranslateAccelerator(g_hWndMain, hAccel, Msg) = 0 THEN
               TranslateMessage Msg
               DispatchMessage Msg
            END IF
         END IF
      WEND
    
      FUNCTION = msg.wParam
    END FUNCTION  ' end WinMain
    
    
    '==============================================================================
    FUNCTION WndProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, _
                      BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
    '------------------------------------------------------------------------------
      ' Main procedure
      '----------------------------------------------------------------------------
    
      LOCAL ToolHeight  AS LONG
      LOCAL StatHeight  AS LONG
      LOCAL dwProc      AS DWORD
      LOCAL hLib        AS DWORD
      LOCAL hMdi        AS DWORD
      LOCAL STYLE       AS DWORD
      LOCAL f           AS STRING
      LOCAL PATH        AS STRING
      LOCAL pt          AS POINTAPI
      LOCAL tRect       AS RECT
      LOCAL mii         AS MENUITEMINFO
      LOCAL tbn         AS TBNOTIFY PTR
      LOCAL lpToolTip   AS TOOLTIPTEXT PTR
      LOCAL cc          AS CLIENTCREATESTRUCT
      LOCAL iccex       AS INIT_COMMON_CONTROLSEX
      LOCAL zText       AS ASCIIZ * %MAX_PATH
    
      SELECT CASE AS LONG wMsg
      CASE %WM_CREATE
          ' Create the MDI Client window
          cc.idFirstChild = 1
          cc.hWindowMenu  = g_hMenuWindow  'for file list in Window menu
          g_hWndClient = CreateWindowEx(%WS_EX_CLIENTEDGE, "MDICLIENT", BYVAL %NULL, _
                                        %WS_CHILD OR %WS_CLIPCHILDREN OR _
                                        %WS_VISIBLE OR %WS_VSCROLL OR %WS_HSCROLL, _
                                        0, 0, 0, 0, hWnd, 1, g_hInst, cc)
    
          '------------------------------------------------------------------------
          ' some of CommCtrl.dll's controls, messages and styles were not included
          ' in standard Win95A release, so we need to see how to initiate the dll.
          '------------------------------------------------------------------------
          g_NewComCtl = InitComctl32 (%ICC_BAR_CLASSES)
    
          '------------------------------------------------------------------------
          ' Create the status bar
          g_hStatus = CreateStatusWindow (%WS_CHILD OR %WS_VISIBLE OR %SBS_SIZEGRIP, _
                                          "", hWnd, %ID_STATUSBAR)
    
          'set up a couple of statusbar parts
          DIM prts(1) AS LONG
          prts(0) = 250 : prts(1) = -1
          Sendmessage g_hStatus, %SB_SETPARTS, 2, VARPTR(prts(0))
          SendMessage g_hStatus, %SB_SETTEXT, 0, VARPTR(zText)
          '------------------------------------------------------------------------
    
          g_hToolbar = MakeToolBar (hWnd)
          EXIT FUNCTION
    
      CASE %WM_SIZE
          IF wParam <> %SIZE_MINIMIZED THEN
              LOCAL HwndMainRect AS RECT
              LOCAL x AS LONG
              LOCAL y AS LONG
              LOCAL xx AS LONG
              LOCAL yy AS LONG
    '*** Get Toolbar and statusbar height
              GetWindowRect HwndMain, HwndMainRect
    MSGBOX STR$(HwndMainRect.nLeft) + "," + STR$(HwndMainRect.nBottom)
              DIALOG PIXELS HwndMain, HwndMainRect.nLeft, HwndMainRect.nBottom TO UNITS HwndMainRect.nLeft, HwndMainRect.nBottom
    MSGBOX STR$(HwndMainRect.nLeft) + "," + STR$(HwndMainRect.nBottom)
    'MSGBOX STR$(xx) + "," + STR$(yy)
    
              GetWindowRect g_hToolbar, tRect
              ToolHeight = tRect.nBottom - tRect.nTop  'toolbar height
              GetWindowRect g_hStatus, tRect
              StatHeight = tRect.nBottom - tRect.nTop  'statusbar height
    
              SendMessage g_hStatus, wMsg, wParam, lParam
              SendMessage g_hToolbar, wMsg, wParam, lParam
              MoveWindow g_hWndClient, -2, ToolHeight, LO(WORD, lParam) + 4, _
                         HI(WORD, lParam) - (ToolHeight + StatHeight), %TRUE
          END IF
          EXIT FUNCTION
    
      CASE %WM_NOTIFY
          tbn = lParam
          IF @tbn.hdr.code = %TTN_NEEDTEXT THEN
              lpToolTip = lParam
              zText = GetStringTable(@lpToolTip.hdr.idFrom)
              @lpToolTip.lpszText = VARPTR(zText)
    
          ELSEIF g_NewComCtl >= 4.7 AND @tbn.hdr.code = %TBN_DROPDOWN THEN
              SELECT CASE AS LONG @tbn.iItem
                  CASE %IDM_OPEN
                      SendMessage @tbn.hdr.hwndFrom, %TB_GETRECT, @tbn.iItem, VARPTR(tRect)
                      MapWindowPoints @tbn.hdr.hwndFrom, %HWND_DESKTOP, BYVAL VARPTR(tRect), 2
                      TrackPopupMenu g_hMenuReopen, 0, tRect.nLeft, tRect.nBottom, 0, hWnd, BYVAL %NULL
              END SELECT
          END IF
          EXIT FUNCTION
    
      CASE %WM_MENUSELECT
          zText = GetStringTable(LOWRD(wParam))
          SendMessage g_hStatus, %SB_SETTEXT, 0, VARPTR(zText)
          EXIT FUNCTION
    
      CASE %WM_NCPAINT 'if flag is set, return zero to avoid menu update
          IF g_FreezeMenu THEN EXIT FUNCTION
    
      CASE %WM_COMMAND
          SELECT CASE AS LONG LO(WORD, wParam)
          CASE %IDM_NEW
              IF MdiGetActive(g_hWndClient) AND _ 'if not first doc and docs are maximized
                 IsZoomed(MdiGetActive(g_hWndClient)) THEN g_FreezeMenu = 1
    
              hMdi = CreateMdiChild($NOTEPADCLASSNAME, g_hWndClient, "", %WS_MAXIMIZE)
    
              IF g_FreezeMenu THEN 'now time to redraw menu
                  g_FreezeMenu = 0
                  DrawMenuBar g_hWndMain
              END IF
              EXIT FUNCTION
    
          CASE %IDM_OPEN
              PATH  = CURDIR$
              f     = "*.txt"
              STYLE = %OFN_FILEMUSTEXIST OR %OFN_HIDEREADONLY OR %OFN_LONGNAMES
              IF OpenFileDialog(g_hWndMain, "", f, PATH, _
                                "Text Files|*.txt|All Files|*.*", "txt", STYLE) THEN
    
                  InvalidateRect g_hToolbar, BYVAL 0, 0
                  UpdateWindow g_hToolbar
                  OpenThisFile f
                  EXIT FUNCTION
              END IF
    
          CASE %IDM_RECENT1 TO %IDM_RECENT8      'MRU menu items (file names)
               IF IsWin95 THEN
                  mii.cbSize   = LEN(mii) - 4           'size of structure
                  mii.fMask    = %MIIM_TYPE OR %MIIM_ID 'set mask
               ELSE
                  mii.cbSize   = LEN(mii)               'size of structure
                  mii.fMask    = %MIIM_FTYPE OR %MIIM_ID OR %MIIM_STRING 'set mask
               END IF
              mii.fType  = %MFT_STRING
              mii.wID    = LO(WORD, wParam)       'selected item
              mii.cch    = %MAX_PATH              'max length of string
              f = SPACE$(%MAX_PATH)               'allocate enough string space
              mii.dwTypeData = STRPTR(f)          'point to allocated string
    
              GetMenuItemInfo g_hMenuReopen,mii.wID,0&,mii  'get string
              f = EXTRACT$(f, CHR$(0))            'cut at zero ending
              f = MID$(f, 4)                      'remove first part - item number
              OpenThisFile f                      'open selected file
    
          CASE %IDM_SAVE   : SAVEFILE %FALSE
          CASE %IDM_SAVEAS : SAVEFILE %TRUE
          CASE %IDM_PRINT  : PrintDocument GetEdit
          CASE %IDM_EXIT   : SendMessage hWnd, %WM_CLOSE, wParam, lParam
    
          CASE %IDM_UNDO    : SendMessage GetEdit, %EM_UNDO, 0, 0
          CASE %IDM_CUT     : SendMessage GetEdit, %WM_CUT, 0, 0
          CASE %IDM_COPY    : SendMessage GetEdit, %WM_COPY, 0, 0
          CASE %IDM_PASTE   : SendMessage GetEdit, %WM_PASTE, 0, 0
          CASE %IDM_DELETE  : SendMessage GetEdit, %WM_CLEAR, 0, 0
          CASE %IDM_SELALL  : SendMessage GetEdit, %EM_SETSEL, 0, -1
    
          CASE %IDM_CASCADE : MdiCascade (g_hWndClient)
          CASE %IDM_TILEH   : MdiTile (g_hWndClient, %MDITILE_HORIZONTAL)
          CASE %IDM_TILEV   : MdiTile (g_hWndClient, %MDITILE_VERTICAL)
          CASE %IDM_ARRANGE : MdiIconArrange (g_hWndClient)
          CASE %IDM_CLOSE
              WHILE MdiGetActive(g_hWndClient)
                  CALL SendMessage(MdiGetActive(g_hWndClient), %WM_CLOSE, 0, 0)
                  IF g_fClosed = 0 THEN EXIT FUNCTION
              WEND
    
          CASE %IDHELP
              WinHelp hWnd, $HELPFILE, %HELP_INDEX, 0&  '<- to show a help file
    
          CASE %IDM_ABOUT  ' Example of how to show Windows built-in AboutDlg
              ShellAbout hWnd, "PBNote2 v1.0#", _
                         "PowerBASIC example - MDI text editor", _
                         LoadIcon(g_hInst, "APPICON")
          END SELECT
    
      CASE %WM_CLOSE
          WHILE MdiGetActive(g_hWndClient)
              CALL SendMessage(MdiGetActive(g_hWndClient), %WM_CLOSE, 0, 0)
              IF g_fClosed = 0 THEN EXIT FUNCTION
          WEND
    
      CASE %WM_DESTROY
          PostQuitMessage 0
          EXIT FUNCTION
    
      CASE %WM_HELP
          WinHelp hWnd, $HELPFILE, %HELP_INDEX, 0&  '<- to show a help file
    
      CASE %WM_SYSCOLORCHANGE
          ' Forward this message to common controls so that they will
          ' be properly updated if a user changes system color settings.
          SendMessage g_hToolbar,  %WM_SYSCOLORCHANGE, wParam, lParam
          SendMessage g_hStatus,  %WM_SYSCOLORCHANGE, wParam, lParam
    
      END SELECT
    
      FUNCTION = DefFrameProc(hWnd, g_hWndClient, wMsg, wParam, lParam)
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION CodeProc (BYVAL hWnd AS DWORD, BYVAL wMsg AS DWORD, _
                       BYVAL wParam AS DWORD, BYVAL lParam AS LONG) AS LONG
    '------------------------------------------------------------------------------
      ' NotePad procedure - handle messages from the MDI child windows.
      '----------------------------------------------------------------------------
    
      LOCAL nFile  AS LONG
      LOCAL dwRes  AS DWORD
      LOCAL hEdit  AS DWORD
      LOCAL hFont  AS DWORD
      LOCAL Buffer AS STRING
      LOCAL pt     AS POINTAPI
      LOCAL rc     AS RECT
      LOCAL zText  AS ASCIIZ * %MAX_PATH
    
      SELECT CASE AS LONG wMsg
      CASE %WM_CREATE
          GetClientRect hWnd, rc
          hEdit = CreateWindowEx(0, "Edit", BYVAL %NULL, %WS_CHILD OR %WS_VISIBLE OR _
                                 %ES_MULTILINE OR %WS_VSCROLL OR %WS_HSCROLL OR _
                                 %ES_AUTOHSCROLL OR %ES_AUTOVSCROLL OR %ES_NOHIDESEL, _
                                 0, 0, rc.nRight, rc.nBottom, hWnd, %IDC_EDIT, g_hInst, BYVAL %NULL)
    
          ' set a fixed width font in the edit control
          hFont = GetStockObject(%ANSI_FIXED_FONT)
          IF hFont THEN SendMessage hEdit, %WM_SETFONT, hFont, 0
    
          ' 32/64 Kb byte limit in Win95/98, but 1 MB limit in NT?
           SendMessage hEdit, %EM_SETLIMITTEXT, &H100000&, 0
    
          GetWindowText hWnd, zText, SIZEOF(zText)
          IF LEN(zText) THEN
              nFile = FREEFILE
              OPEN zText FOR BINARY AS nFile LEN = 8192
              IF ERR THEN
                  BEEP
                  DestroyWindow hWnd
                  EXIT FUNCTION
              END IF
    
              GET$ nFile, LOF(nFile), Buffer
              CLOSE nFile
              SetWindowText hEdit, BYVAL STRPTR(Buffer)
              WriteRecentFiles zText  ' refresh reopen file list
    
          ELSE
              INCR g_NewDocNum
              SetWindowText hWnd, "Untitled" & STR$(g_NewDocNum)
          END IF
    
          IF MdiGetActive(g_hWndClient) = 0 THEN HideButtons 0 'if first doc
          EXIT FUNCTION
    
      CASE %WM_SIZE
          IF wParam <> %SIZE_MINIMIZED THEN
              hEdit = GetDlgItem(hWnd, %IDC_EDIT)
              MoveWindow hEdit, 0, 0, LOWRD(lParam), HIWRD(lParam), 1
              SendMessage hEdit, %EM_GETRECT, 0, VARPTR(rc) 'for margins in editor
              rc.nTop  = 2 ' pixels, top margin
              rc.nLeft = 3 ' pixels, left margin
              rc.nBottom = rc.nBottom + 2 ' increase bottom part a bit
              SendMessage hEdit, %EM_SETRECTNP, 0, BYVAL VARPTR(rc)
          END IF
    
      CASE %WM_SETFOCUS
          SetFocus GetEdit
          EXIT FUNCTION
    
      CASE %WM_CLOSE
          IF SendMessage(GetEdit, %EM_GETMODIFY, 0, 0) THEN
              GetWindowText hWnd, zText, SIZEOF(zText)
    
              Buffer = "Save changes to " & FileNam(zText) & " ?"
              dwRes  = MessageBox(hWnd, BYVAL STRPTR(Buffer), "Save file", _
                                  %MB_YESNOCANCEL OR %MB_ICONEXCLAMATION)
    
              IF dwRes = %IDCANCEL THEN
                  g_fClosed = %FALSE
                  EXIT FUNCTION
              ELSEIF dwRes = %IDYES THEN
                  SAVEFILE %FALSE
              END IF
          END IF
          g_fClosed = %TRUE
    
          dwRes = GetWindow(g_hWndClient, %GW_CHILD)
          IF GetWindow(dwRes, %GW_HWNDNEXT) = 0 THEN 'if this is last doc
              HideButtons %TRUE
          END IF
    
      CASE %WM_DESTROY
          IF MdiGetActive(g_hWndClient) = 0 THEN    'if last one closed
              g_NewDocNum = 0                       'reset doc counter
          END IF
    
      END SELECT
    
      FUNCTION = DefMDIChildProc(hWnd, wMsg, wParam, lParam)
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION FileExist(BYVAL sfName AS STRING) AS LONG
    '------------------------------------------------------------------------------
      ' FileExist - make sure a file or folder exists
      '----------------------------------------------------------------------------
      LOCAL hRes AS DWORD, tWFD AS WIN32_FIND_DATA
    
      IF LEN(sfName) = 0 THEN EXIT FUNCTION       'no need to continue then..
      IF ASC(sfName, -1) = 92 THEN                'if a path with trailing backslash
          sfName = LEFT$(sfName, LEN(sfName) - 1) 'remove trailing backslash
      END IF
      '----------------------------------------------------------------------------
      hRes = FindFirstFile(BYVAL STRPTR(sfName), tWFD)
      IF hRes <> %INVALID_HANDLE_VALUE THEN
          FUNCTION = %TRUE
          FindClose hRes
      END IF
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION FileNam (BYVAL Src AS STRING) AS STRING
    '------------------------------------------------------------------------------
      ' Get file name part of given path & name
      '----------------------------------------------------------------------------
      LOCAL x AS LONG
    
      x = INSTR(-1, Src, ANY ":/\")
      IF x THEN
          FUNCTION = MID$(Src, x + 1)
      ELSE
          FUNCTION = Src
      END IF
    
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION FilePath (BYVAL Src AS STRING) AS STRING
    '------------------------------------------------------------------------------
      ' Get path -part of given path & name
      '----------------------------------------------------------------------------
      LOCAL x AS LONG
    
      x = INSTR(-1, Src, ANY ":\/")
      IF x THEN
          FUNCTION = LEFT$(Src, x)
      ELSE
          FUNCTION = Src
      END IF
    
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION GetEdit() AS LONG
    '------------------------------------------------------------------------------
      ' Get active MDI child's edit control, if any
      '----------------------------------------------------------------------------
      FUNCTION = GetDlgItem(MdiGetActive(g_hWndClient), %IDC_EDIT)
    END FUNCTION
    
    
    '==============================================================================
    SUB GetRecentFiles
    '------------------------------------------------------------------------------
      ' Read the list of recently opened files and rebuild the Recent files submenu
      '----------------------------------------------------------------------------
      LOCAL Bc AS LONG, lRes AS LONG
      LOCAL InString AS ASCIIZ * 300
      LOCAL zSection AS ASCIIZ * 30, zKey AS ASCIIZ * 30, zDefault AS ASCIIZ * 30
    
      '----------------------------------------------------------------------------
      ' First clear the Recent file submenu from all items
      '----------------------------------------------------------------------------
      FOR Bc = 1 TO GetMenuItemCount(g_hMenuReopen)
          MENU DELETE g_hMenuReopen, 1
      NEXT Bc
    
      '----------------------------------------------------------------------------
      ' Then Rebuild it with items via file names stored in the ini file
      '----------------------------------------------------------------------------
      Bc = 1
      zSection = "Reopen files"
      DO
          zKey = "File " & FORMAT$(Bc)
          lRes = GetPrivateProfileString(zSection, zKey, zDefault, InString, %MAX_PATH, g_zIni)
    
          IF lRes THEN
              InString = "&" & FORMAT$(Bc) & " " & LEFT$(InString, lRes)
              MENU ADD STRING, g_hMenuReopen, InString, %IDM_RECENT1 + Bc - 1, %MF_ENABLED
          ELSE
              EXIT DO
          END IF
          INCR Bc
          IF Bc > 8 THEN EXIT DO
      LOOP
    
    END SUB
    
    
    '==============================================================================
    FUNCTION GetStringTable(BYVAL ID AS LONG) AS STRING
    '------------------------------------------------------------------------------
      ' Return a id related string table text
      '----------------------------------------------------------------------------
      SELECT CASE AS LONG ID
      CASE %IDM_NEW      : FUNCTION = " Open a new document"
      CASE %IDM_OPEN     : FUNCTION = " Open an existing file"
      CASE %IDM_SAVE     : FUNCTION = " Save file directly"
      CASE %IDM_SAVEAS   : FUNCTION = " Save file via dialog"
      CASE %IDM_PRINT    : FUNCTION = " Print active document"
      CASE %IDM_EXIT     : FUNCTION = " Close PBNote2"
      CASE %IDM_UNDO     : FUNCTION = " Undo last action"
      CASE %IDM_CUT      : FUNCTION = " Cut to clipboard"
      CASE %IDM_COPY     : FUNCTION = " Copy to clipboard"
      CASE %IDM_PASTE    : FUNCTION = " Paste from clipboard"
      CASE %IDM_DELETE   : FUNCTION = " Delete selected text"
      CASE %IDM_SELALL   : FUNCTION = " Select all text"
      CASE %IDM_CASCADE  : FUNCTION = " Cascade windows"
      CASE %IDM_TILEH    : FUNCTION = " Tile windows horizontally"
      CASE %IDM_TILEV    : FUNCTION = " Tile windows vertically"
      CASE %IDM_ARRANGE  : FUNCTION = " Arrange minimized windows"
      CASE %IDM_CLOSE    : FUNCTION = " Close all windows"
      CASE %IDHELP       : FUNCTION = " Show help file"
      CASE %IDM_ABOUT    : FUNCTION = " About PBNote2"
      END SELECT
    END FUNCTION
    
    
    '==============================================================================
    SUB HideButtons (BYVAL HideState AS LONG)
    '------------------------------------------------------------------------------
      ' Show/hide buttons and enable/disable menus
      '----------------------------------------------------------------------------
      LOCAL ITEM AS DWORD, mFlag AS DWORD
    
      IF GetSubMenu(g_hMenu, 0) = g_hMenuFile THEN ITEM = 1 ELSE ITEM = 2
      IF HideState THEN mFlag = %MF_GRAYED ELSE mFlag = %MF_ENABLED
    
      EnableMenuItem g_hMenu, ITEM, %MF_BYPOSITION OR mFlag
      EnableMenuItem g_hMenu, ITEM + 1, %MF_BYPOSITION OR mFlag
      EnableMenuItem g_hMenuFile, %IDM_SAVE,   %MF_BYCOMMAND OR mFlag
      EnableMenuItem g_hMenuFile, %IDM_SAVEAS, %MF_BYCOMMAND OR mFlag
      EnableMenuItem g_hMenuFile, %IDM_PRINT,  %MF_BYCOMMAND OR mFlag
      DrawMenuBar g_hWndMain
    
      SendMessage g_hToolbar, %TB_HIDEBUTTON, %IDM_UNDO, HideState
      SendMessage g_hToolbar, %TB_HIDEBUTTON, 703, HideState
      SendMessage g_hToolbar, %TB_HIDEBUTTON, %IDM_PASTE, HideState
      SendMessage g_hToolbar, %TB_HIDEBUTTON, %IDM_COPY, HideState
      SendMessage g_hToolbar, %TB_HIDEBUTTON, %IDM_CUT, HideState
      SendMessage g_hToolbar, %TB_HIDEBUTTON, 702, HideState
      SendMessage g_hToolbar, %TB_HIDEBUTTON, %IDM_PRINT, HideState
      SendMessage g_hToolbar, %TB_HIDEBUTTON, 701, HideState
      SendMessage g_hToolbar, %TB_HIDEBUTTON, %IDM_SAVE, HideState
    
    END SUB
    
    
    '==============================================================================
    FUNCTION IsWin95() AS LONG
    '------------------------------------------------------------------------------
      ' Return true if OS is Windows 95
      '----------------------------------------------------------------------------
      LOCAL vi AS OSVERSIONINFO
    
      vi.dwOsVersionInfoSize = SIZEOF(vi)
      GetVersionEx vi
    
      FUNCTION = ((vi.dwPlatformId = %VER_PLATFORM_WIN32_WINDOWS) AND (vi.dwMinorVersion = 0))
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION MakeAccelerators() AS DWORD
    '------------------------------------------------------------------------------
      ' Create an Accelerator table for keyboard shortcuts
      '-----------------------------------------------------------------------------
      DIM c AS LONG, ac(9) AS ACCELAPI  ' for keyboard accelator table values
    
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_O : ac(c).cmd   = %IDM_OPEN   : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_N : ac(c).cmd   = %IDM_NEW    : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_S : ac(c).cmd   = %IDM_SAVE   : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_P : ac(c).cmd   = %IDM_PRINT  : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_Z : ac(c).cmd   = %IDM_UNDO   : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_X : ac(c).cmd   = %IDM_CUT    : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_C : ac(c).cmd   = %IDM_COPY   : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_V : ac(c).cmd   = %IDM_PASTE  : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_A : ac(c).cmd   = %IDM_SELALL : INCR c
      ac(c).fvirt = %FVIRTKEY OR %FCONTROL : ac(c).key   = %VK_Q : ac(c).cmd   = %IDM_EXIT   : INCR c
    
      FUNCTION = CreateAcceleratorTable(ac(0), UBOUND(ac))
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION MakeMenu (BYVAL hWnd AS DWORD) AS DWORD
    '------------------------------------------------------------------------------
      ' Create a menu
      '----------------------------------------------------------------------------
      LOCAL hMnu AS DWORD, hSubMenu AS DWORD, hSubMenu2 AS DWORD
    
      MENU NEW BAR TO hMnu
         MENU NEW POPUP TO hSubMenu
         MENU ADD POPUP, hMnu, "&File", hSubMenu, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "&New"  + $TAB + "Ctrl+N", %IDM_NEW,  %MF_ENABLED
            MENU ADD STRING, hSubMenu, "&Open" + $TAB + "Ctrl+O", %IDM_OPEN, %MF_ENABLED
            MENU NEW POPUP TO hSubMenu2
            MENU ADD POPUP, hSubMenu, "&Reopen...", hSubMenu2, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "-", 0, 0
            MENU ADD STRING, hSubMenu, "&Save" + $TAB + "Ctrl+S", %IDM_SAVE, %MF_GRAYED
            MENU ADD STRING, hSubMenu, "Save &As", %IDM_SAVEAS, %MF_GRAYED
            MENU ADD STRING, hSubMenu, "-", 0, 0
            MENU ADD STRING, hSubMenu, "&Print.." + $TAB + "Ctrl+P", %IDM_PRINT, %MF_GRAYED
            MENU ADD STRING, hSubMenu, "-", 0, 0
            MENU ADD STRING, hSubMenu, "E&xit" + $TAB + "Alt+F4", %IDM_EXIT, %MF_ENABLED
         MENU NEW POPUP TO hSubMenu
         MENU ADD POPUP, hMnu, "&Edit", hSubMenu, %MF_GRAYED
            MENU ADD STRING, hSubMenu, "Undo" + $TAB + "Ctrl+Z", %IDM_UNDO, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "-", 0, 0
            MENU ADD STRING, hSubMenu, "Cut" + $TAB + "Ctrl+X", %IDM_CUT, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "Copy" + $TAB + "Ctrl+C", %IDM_COPY, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "Paste" + $TAB + "Ctrl+V", %IDM_PASTE, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "Delete" + $TAB + "Delete", %IDM_DELETE, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "-", 0, 0
            MENU ADD STRING, hSubMenu, "Select &all" + $TAB + "Ctrl+A", %IDM_SELALL, %MF_ENABLED
         MENU NEW POPUP TO hSubMenu
         MENU ADD POPUP, hMnu, "&Window", hSubMenu, %MF_GRAYED
            MENU ADD STRING, hSubMenu, "&Cascade", %IDM_CASCADE, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "&Tile horizontally", %IDM_TILEH, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "&Tile vertically", %IDM_TILEV, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "-", 0, 0
            MENU ADD STRING, hSubMenu, "Arrange &Icons", %IDM_ARRANGE, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "Close &All", %IDM_CLOSE, %MF_ENABLED
         MENU NEW POPUP TO hSubMenu
         MENU ADD POPUP, hMnu, "&Help", hSubMenu, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "&Help", %IDHELP, %MF_ENABLED
            MENU ADD STRING, hSubMenu, "-", 0, 0
            MENU ADD STRING, hSubMenu, "&About", %IDM_ABOUT, %MF_ENABLED
    
      FUNCTION = hMnu
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION MakeToolBar (BYVAL hWnd AS DWORD) AS DWORD
    '------------------------------------------------------------------------------
      ' Setup and create the ToolBar
      '----------------------------------------------------------------------------
      LOCAL c AS LONG, hToolBar AS DWORD
      DIM tbb(10) AS TBBUTTON  'for 11 buttons, including separators
    
      ' Fill the TBBUTTON array with button information
      tbb(c).iBitmap   = %STD_FILENEW
      tbb(c).idCommand = %IDM_NEW
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_BUTTON
      INCR c
    
      tbb(c).iBitmap   = %STD_FILEOPEN
      tbb(c).idCommand = %IDM_OPEN
      tbb(c).fsState   = %TBSTATE_ENABLED
      IF g_NewComCtl >= 4.7 THEN
         tbb(c).fsStyle = %TBSTYLE_DROPDOWN
      ELSE
         tbb(c).fsStyle = %TBSTYLE_BUTTON
      END IF
      INCR c
    
      tbb(c).iBitmap   = %STD_FILESAVE
      tbb(c).idCommand = %IDM_SAVE
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_BUTTON
      INCR c
    
      tbb(c).iBitmap   = 0
      tbb(c).idCommand = 701
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_SEP
      INCR c
    
      tbb(c).iBitmap   = %STD_PRINT
      tbb(c).idCommand = %IDM_PRINT
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_BUTTON
      INCR c
    
      tbb(c).iBitmap   = 0
      tbb(c).idCommand = 702
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_SEP
      INCR c
    
      tbb(c).iBitmap   = %STD_CUT
      tbb(c).idCommand = %IDM_CUT
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_BUTTON
      INCR c
    
      tbb(c).iBitmap   = %STD_COPY
      tbb(c).idCommand = %IDM_COPY
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_BUTTON
      INCR c
    
      tbb(c).iBitmap   = %STD_PASTE
      tbb(c).idCommand = %IDM_PASTE
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_BUTTON
      INCR c
    
      tbb(c).iBitmap   = 0
      tbb(c).idCommand = 703
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_SEP
      INCR c
    
      tbb(c).iBitmap   = %STD_UNDO
      tbb(c).idCommand = %IDM_UNDO
      tbb(c).fsState   = %TBSTATE_ENABLED
      tbb(c).fsStyle   = %TBSTYLE_BUTTON
      INCR c
    
      hToolBar = CreateToolbarEx (hWnd, %WS_CHILD OR %WS_VISIBLE OR %TBSTYLE_TOOLTIPS, _
                                  %ID_TOOLBAR, 12, %HINST_COMMCTRL, %IDB_STD_SMALL_COLOR, _
                                  tbb(0), UBOUND(tbb) + 1, 0, 0, 16, 15, LEN(TBBUTTON))
    
      IF hToolBar THEN
          SendMessage hToolBar, %TB_AUTOSIZE, 0, 0
          IF g_NewComCtl >= 4.7 THEN ' then we can use more modern features, like flat style, etc.
             SetWindowLong hToolBar, %GWL_STYLE, _
                GetWindowLong(hToolbar, %GWL_STYLE) OR %TBSTYLE_FLAT
             SendMessage hToolBar, %TB_SETEXTENDEDSTYLE, 0, %TBSTYLE_EX_DRAWDDARROWS
          END IF
      END IF
    
      FUNCTION = hToolBar
    
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION OpenThisFile(BYVAL fn AS STRING) AS DWORD
    '------------------------------------------------------------------------------
      ' Open file procedure
      '----------------------------------------------------------------------------
      LOCAL hMdi AS DWORD, zText AS ASCIIZ * %MAX_PATH
    
      hMdi = GetWindow(g_hWndClient, %GW_CHILD) 'first look at already opened docs
      WHILE hMdi
          GetWindowText hMdi, zText, %MAX_PATH
          IF UCASE$(zText) = UCASE$(fn) THEN                     'if already opened
              SendMessage g_hWndClient, %WM_MDIACTIVATE, hMdi, 0  'activate it
              WriteRecentFiles fn                                 'update MRU menu and exit
              EXIT FUNCTION
          END IF
          hMdi = GetWindow(hMdi, %GW_HWNDNEXT)
      WEND
      '------------------------------------------------------------------------------
      IF MdiGetActive(g_hWndClient) AND _      'if not first doc and docs are maximized
         IsZoomed(MdiGetActive(g_hWndClient)) THEN g_FreezeMenu = 1 'turn off menu redraw
    
      hMdi = CreateMdiChild($NOTEPADCLASSNAME, g_hWndClient, fn, %WS_MAXIMIZE)
    
      IF g_FreezeMenu THEN          'if menu redraw was turned off
          g_FreezeMenu = 0          'reset flag
          DrawMenuBar g_hWndMain    'and redraw menu
      END IF
    
      FUNCTION = hMdi
    END FUNCTION
    
    
    '==============================================================================
    FUNCTION GetLineText (BYVAL hEdit AS DWORD, BYVAL ln AS LONG) AS STRING
    '------------------------------------------------------------------------------
      ' Get desired line of text from the edit control
      '----------------------------------------------------------------------------
      LOCAL lnStart, lnLen AS LONG, Buf AS STRING
    
      lnStart = SendMessage(hEdit, %EM_LINEINDEX, ln, 0)       'line start
      lnLen   = SendMessage(hEdit, %EM_LINELENGTH, lnStart, 0) 'line length
    
      IF lnLen THEN
         Buf = SPACE$(lnLen)
         lnLen = SendMessage(hEdit, %EM_GETLINE, ln, STRPTR(Buf)) 'Get line
         IF lnLen THEN FUNCTION = Buf
      END IF
    
    END FUNCTION
    
    
    '==============================================================================
    SUB PrintDocument (BYVAL hEdit AS DWORD)
    '------------------------------------------------------------------------------
      ' Basic print procedure - prints the contents of an edit control (TextBox)
      ' with 0.8 inch margins (about 20 mm) and a header at top of each page.
      '----------------------------------------------------------------------------
      LOCAL c, x, y, x1, y1, x2, y2, w, h, w1, h1, pgNum, ppiX, ppiY AS LONG
      LOCAL sHeader  AS STRING
      LOCAL zDocName AS ASCIIZ * %MAX_PATH
    
      '----------------------------------------------------------------------------
      ' Grab document title (file name) for the header
      GetWindowText MdiGetActive(g_hWndClient), zDocName, SIZEOF(zDocName)
      zDocName = FileNam(zDocName)
    
      '----------------------------------------------------------------------------
      ERRCLEAR
      XPRINT ATTACH CHOOSE, "PBNote2 - " + TRIM$(zDocName)  ' Attach the default host printer
    
      IF ERR = 0 AND LEN(XPRINT$) THEN          ' On success
          XPRINT GET SIZE TO w, h               ' Get page size in pixels
          XPRINT GET MARGIN TO x1, y1, x2, y2   ' Get printer margins
          XPRINT GET PPI TO ppiX, ppiY          ' Get resolution in pixels/inch
          ' (For resolution in pixels/centimeter, divide ppiX and ppiY with 25.4)
    
          x1 = 0.8 * (ppiX - x1)            ' 0.8 inch user-defined left margin
          y1 = 0.8 * (ppiY - y1)            ' 0.8 inch user-defined top margin
    
          XPRINT FONT "Courier New", 10, 0  ' Set a 10 p fixed-width font
          GOSUB PrintPageHeader             ' Begin by printing a header
    
          y2 = h - (0.8 * ppiY) - y2 - h1   ' calculate the bottom margin pos
    
          '------------------------------------------------------------------------
          FOR c = 0 TO SendMessage(hEdit, %EM_GETLINECOUNT, 0, 0) - 1
              XPRINT GET POS TO x, y        ' check position
    
              IF y > y2 THEN                ' if we end up below bottom margin pos
                  XPRINT FORMFEED           ' eject paper and start new page
                  GOSUB PrintPageHeader     ' Print header part
              ELSE
                  XPRINT SET POS (x1, y)    ' else simply set position
              END IF
    
              XPRINT GetLineText(hEdit, c)  ' and print line
          NEXT
          '------------------------------------------------------------------------
    
          XPRINT CLOSE                      ' End printjob and detach the printer
      END IF
    
    EXIT SUB
    
    '--------------------------------------------------------------------
    PrintPageHeader:
      INCR pgNum      ' print a right-aligned header at top of page
      sHeader = TRIM$(zDocName) + "  -  Page" + STR$(pgNum)
      XPRINT TEXT SIZE sHeader TO w1, h1
      XPRINT SET POS (w - w1 - x1, 0.3 * y1)
      XPRINT sHeader
      y = y1
      XPRINT SET POS (x1, y) ' set position for actual text
    RETURN
    
    END SUB
    
    
    '==============================================================================
    SUB SAVEFILE (BYVAL Ask AS LONG)
    '------------------------------------------------------------------------------
      ' Save as -procedure
      '----------------------------------------------------------------------------
      LOCAL dwStyle AS DWORD
      LOCAL nFile   AS DWORD
      LOCAL PATH    AS STRING
      LOCAL f       AS STRING
      LOCAL Buffer  AS STRING
      LOCAL zText   AS ASCIIZ * %MAX_PATH
    
      '----------------------------------------------------------------------------
      GetWindowText MdiGetActive(g_hWndClient), zText, SIZEOF(zText)
      IF INSTR(zText, ANY ":\/") = 0 THEN 'if no path, it's a new doc (Untitled 1, etc)
           PATH = CURDIR$
           IF RIGHT$(PATH, 1) <> "\" THEN PATH = PATH + "\"
           f    = REMOVE$(zText, " ") & ".txt"  'suggest this name - remove space
           Ask  = %TRUE           'we need the dialog for new docs
      ELSE
           PATH = FilePath(zText)
           f    = FileNam(zText)
      END IF
      dwStyle = %OFN_FILEMUSTEXIST OR %OFN_HIDEREADONLY OR _
                %OFN_EXPLORER OR %OFN_OVERWRITEPROMPT
    
      '----------------------------------------------------------------------------
      IF Ask THEN
         IF SaveFileDialog(g_hWndMain, "", f, PATH, _
            "Text Files|*.txt|All Files|*.*", "txt", dwStyle) = 0 THEN EXIT SUB
      ELSE
         f = PATH & f
      END IF
    
      '----------------------------------------------------------------------------
      nFile = FREEFILE  'time to save the file
      OPEN f FOR BINARY AS nFile
        IF ERR THEN   ' if something went wrong
            MSGBOX "Following error occured while trying to save the file:" + $CRLF + _
                   "Error:" + STR$(ERR) + ", " + ERROR$(ERR)+ $CRLF + $CRLF + _
                   "The file could not be saved.", _
                   %MB_ICONWARNING OR %MB_OK OR %MB_TASKMODAL, _
                   "Save file error!"
            EXIT SUB
        END IF
    
         Buffer = SPACE$(GetWindowTextLength(GetEdit) + 1)
         GetWindowText GetEdit, BYVAL STRPTR(Buffer), LEN(Buffer)
         PUT$ nFile, LEFT$(Buffer, LEN(Buffer) - 1)
         SETEOF nFile
      CLOSE nFile
    
      '----------------------------------------------------------------------------
      IF Ask THEN 'if dialog, update caption in case name was changed
          SetWindowText MdiGetActive(g_hWndClient), BYVAL STRPTR(f)
      END IF
      SendMessage GetEdit, %EM_SETMODIFY, 0, 0
      WriteRecentFiles f   'finally, update reopen file list (MRU menu)
    
    END SUB
    
    
    '==============================================================================
    SUB WriteRecentFiles (BYVAL OpenFName AS STRING)
    '------------------------------------------------------------------------------
      ' Save the list of recently opened files
      '----------------------------------------------------------------------------
      LOCAL Ac AS LONG, dwRes AS DWORD, zText AS ASCIIZ * %MAX_PATH
      LOCAL zSection AS ASCIIZ * 30, zKey AS ASCIIZ * 30, zDefault AS ASCIIZ * 30
    
      DIM IniName(1 : 8) AS STRING
      zSection = "Reopen files"
    
      ' Read current Recent files list from ini file into an array
      FOR Ac = 1 TO 8
          zKey = "File " & FORMAT$(Ac)
          dwRes = GetPrivateProfileString(zSection, zKey, zDefault, zText, %MAX_PATH, g_zIni)
          IF dwRes THEN IniName(Ac) = LEFT$(zText, dwRes)
      NEXT Ac
    
      ' Compare existing Recent file names with current file
      Ac = 0
      ARRAY SCAN IniName(), COLLATE UCASE, = UCASE$(OpenFName), TO Ac
      IF Ac THEN ARRAY DELETE IniName(Ac)
      ARRAY INSERT IniName(), OpenFName
    
      ' Save the array to ini file
      FOR Ac = 1 TO 8
          IF LEN(IniName(Ac)) THEN
              zKey   = "File " & FORMAT$(Ac)
              zText = IniName(Ac)
              WritePrivateProfileString zSection, zKey, zText, g_zIni
          END IF
      NEXT Ac
    
      GetRecentFiles 'update MRU menu
    
    END SUB
    So am I looking at something I did? or an MDI vs SDI problem? or a (shudder) "Bug"??? Or any idea what I should be looking into???
    My only clues at the time are DDT vs SDK, or MDI vs SDI, or SOMETHING I am overlooking?????

    My only clue is the offending line is " DIALOG PIXELS HwndMain, HwndMainRect.nLeft, HwndMainRect.nBottom TO UNITS HwndMainRect.nLeft, HwndMainRect.nBottom
    "
    and it does not matter if I change the "HwndMainRect.nLeft, HwndMainRect.nBottom" to xx, yy so I am at a loss????
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

    #2
    If you think the problem is occuring in WM_SIZE...
    Code:
    %WM_SIZE
              LOCAL HwndMainRect AS RECT
              LOCAL x AS LONG
              LOCAL y AS LONG
              LOCAL xx AS LONG
              LOCAL yy AS LONG
    '*** Get Toolbar and statusbar height
              GetWindowRect HwndMain, HwndMainRect
    MSGBOX STR$(HwndMainRect.nLeft) + "," + STR$(HwndMainRect.nBottom)
              DIALOG PIXELS HwndMain, HwndMainRect.nLeft, HwndMainRect.nBottom TO UNITS HwndMainRect.nLeft, HwndMainRect.nBottom
    MSGBOX STR$(HwndMainRect.nLeft) + "," + STR$(HwndMainRect.nBottom)
    'MSGBOX STR$(xx) + "," + STR$(yy)
    ... first thing get the MSGBOXs out of there. Those run more-or-less asyncronously and you can be creating re-entrancy problems. Use TRACE PRINT or STDOUT or write to a log file or something else.

    I'd go for the TRACE PRINT for the simple reason I'd like to see how far the program gets before it faults out. TRACE is great for that.

    The PBNOTE2 example is moot, since that window is already created in Pixels and I don't know why you'd want dialog units... and although I doubt this would be a problem, DIALOG PIXELS TO UNITS is a DDT command being used against a non-DDT window.

    Lastly, you have enough experience by now to know that when you get a protection fault termination in a "wicked huge program", the 'real' error could have occurred many many instructions ago; that is, whatever is really happening on WM_SIZE (code shown does nothing except calculate some dimensions) is just the first place some earlier untrapped error exhibits itself.

    First thing I'd do is enable a TRACE in "wicked huge program" and see if that can get me to a place where the real problem can be isolated.
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


      #3
      It appears you are partially right. However I did discover if trying to go from Units to Pixels then no problems.

      SDK Tests
      Code:
      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      ' Declares
      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      #COMPILE EXE
      #INCLUDE "WIN32API.INC"
      '----------------------------------------------------------------------
      GLOBAL g_hInst        AS DWORD
      GLOBAL g_hWndMain     AS DWORD
      GLOBAL g_hMenu        AS DWORD
      
      '----------------------------------------------------------------------
      DECLARE FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                                BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
      
      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      ' Program entrance
      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      FUNCTION WINMAIN (BYVAL hInst AS LONG, BYVAL hPrevInstance AS LONG, _
                        BYVAL lpszCmdLine AS ASCIIZ PTR, BYVAL nCmdShow AS LONG) AS LONG
      TRACE NEW "ErrorLog.txt"
      TRACE ON
        LOCAL hDlg AS LONG, hCtl AS LONG, hFont AS LONG, _
              wce AS WndClassEx, szClassName AS ASCIIZ * 80
      
        hFont = GetStockObject(%ANSI_VAR_FONT)
      
        ' Register Main Window Class
        szClassName       = "TestSdk"
        wce.cbSize        = SIZEOF(wce)
        wce.STYLE         = %CS_HREDRAW OR %CS_VREDRAW
        wce.lpfnWndProc   = CODEPTR(WndProc)
        wce.cbClsExtra    = 0
        wce.cbWndExtra    = 0
        wce.hInstance     = g_hInst
        wce.hIcon         = LoadIcon(g_hInst, "APPICON")
        IF wce.hIcon = 0 THEN 'if no resource icon, give it a system icon..
           wce.hIcon = LoadIcon(0, BYVAL %IDI_APPLICATION)
        END IF
        wce.hCursor       = LoadCursor(%NULL, BYVAL %IDC_ARROW)
        wce.hbrBackground = %NULL
        wce.lpszMenuName  = %NULL
        wce.lpszClassName = VARPTR(szClassName)
        wce.hIconSm       = LoadIcon(g_hInst, BYVAL %IDI_APPLICATION)
      
        IF RegisterClassEx(wce) = 0 THEN
            RegisterClass BYVAL (VARPTR(wce) + 4)
        END IF
        g_hWndMain = CreateWindow("TestSdk", _      ' Main window's class name
                                  "TestSdk", _      ' Main window's initial caption
                                  %WS_OVERLAPPEDWINDOW, _   ' window style
                                  (GetSystemMetrics(%SM_CXSCREEN) - 640) / 2, _  ' initial x position
                                  (GetSystemMetrics(%SM_CYSCREEN) - 480) / 2, _  ' initial y position
                                  640, _                    ' initial x size
                                  480, _                    ' initial y size
                                  %NULL, _                  ' parent window handle
                                  g_hMenu, _                ' window menu handle
                                  g_hInst, _                ' program instance handle
                                  BYVAL %NULL)              ' creation parameters
      
        ShowWindow g_hWndMain, nCmdShow
        UpdateWindow g_hWndMain
      
        LOCAL Msg AS tagMsg
        WHILE GetMessage(Msg, %NULL, 0, 0)<>0
           TranslateMessage Msg
           DispatchMessage Msg
        WEND
      
        FUNCTION = msg.wParam
      END FUNCTION
      
      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      ' Main Window procedure
      '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
      FUNCTION WndProc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, _
                        BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
      TRACE ON
        SELECT CASE wMsg
           CASE %WM_CREATE
           CASE %WM_COMMAND
           CASE %WM_DESTROY
              PostQuitMessage 0
              FUNCTION = 0 : EXIT FUNCTION
           CASE %WM_SIZE
              IF wParam <> %SIZE_MINIMIZED THEN
                LOCAL HwndMainRect AS RECT
                LOCAL x AS LONG
                LOCAL y AS LONG
                LOCAL xx AS LONG
                LOCAL yy AS LONG
      '*** Get Toolbar and statusbar height
                GetWindowRect g_hWndMain, HwndMainRect
      #DEBUG PRINT STR$(HwndMainRect.nLeft) + "," + STR$(HwndMainRect.nBottom)
      '*** None of the below work PIXELS ---> UNITS
      '          DIALOG PIXELS g_hWndMain, HwndMainRect.nLeft, HwndMainRect.nBottom TO UNITS HwndMainRect.nLeft, HwndMainRect.nBottom
      '          DIALOG PIXELS g_hWndMain, HwndMainRect.nLeft, HwndMainRect.nBottom TO UNITS xx, yy
      '          DIALOG PIXELS g_hWndMain, 480, 840 TO UNITS xx, yy
      '          DIALOG PIXELS g_hWndMain, x, y TO UNITS xx, yy
      '*** Reverse the order though and no crash UNITS ---> PIXELS
                DIALOG UNITS g_hWndMain, x, y TO PIXELS xx, yy
      '          DIALOG PIXELS g_hWndMain, x, y TO UNITS xx, yy
      #DEBUG PRINT STR$(HwndMainRect.nLeft) + "," + STR$(HwndMainRect.nBottom)
              END IF
        END SELECT
        FUNCTION = DefWindowProc(hWnd, wMsg, wParam, lParam)
      END FUNCTION
      DDT Tests ---> Code not shown due to no problems using PB commands on DDT windows, so works as advertised.

      Maybe I should submit this to PB??? (But the back of my mind I could swear this affect is already documented????
      Engineer's Motto: If it aint broke take it apart and fix it

      "If at 1st you don't succeed... call it version 1.0"

      "Half of Programming is coding"....."The other 90% is DEBUGGING"

      "Document my code????" .... "WHYYY??? do you think they call it CODE? "

      Comment


        #4
        Let me re-guess...

        DIALOG UNITS to PIXELS and PIXELS TO UNITS may in Fact be "DDT windows only" if PB saves the dimensions internally and converts on the fly (as you can do yourself).... then when it tries to find the "UNITS" in a screen it is not managing it finds NOTHING.

        Does your x00005 exception report the failing address as 0x0000000 (Null pointer)? If so, that would kind of tend to support this theory.

        Let's see, converting units to Pixels... start with the GetDlgBaseUnits() function. I think the two-step formula is on the SDK reference page for that. I think MapWindowPoints() might work, too.

        But why you'd be working with UNITS on a non-DDT window is a mystery.. all SDK operations on non-dialog windows return or use nothing but pixels; and even with SDK-Created dialogs, I think dialog units are used ONLY in the CreateDialog[Indirect] or DialogBox[Indirect] calls.. after that everything is done in pixels.




        MCM
        Last edited by Michael Mattias; 7 Jul 2009, 07:00 PM.
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


          #5
          DIALOG UNITS to PIXELS and PIXELS TO UNITS may in Fact be "DDT windows only" if PB saves the dimensions internally and converts on the fly (as you can do yourself).... then when it tries to find the "UNITS" in a screen it is not managing it finds NOTHING.
          if PB saves the dimensions internally and converts on the fly (as you can do yourself)
          OK so how do I do that??? to my knowledge I can only get pixels....and it may be my fatal flaw (as in math...the moment you forget units, the math is flawed)

          Does your x00005 exception report the failing address as 0x0000000 (Null pointer)? If so, that would kind of tend to support this theory.
          I will have to check under XP in the morning, cause Vista (at least in my case) either wants me to report, or debug.....and nothing to debug with outside trace, pb, pbdebug, anything short of somehow hooking my own program.
          Although the memory addresses are REALLY familiar (like I have not seen them before )

          But why you'd be working with UNITS on a non-DDT window is a mystery.. all SDK operations on non-dialog windows return or use nothing but pixels;
          Well I did say I was trying to clean up mistakes of the past, (mix and match SDK with DDT) so reading docs I thought converting values in DDT (Dialog Units) to SDK (Pixels) would be one to try to look at.....(I knever knew though why (fully) why it involved a Dialog (sort of like Pixels vs Twips vs Dialog Units vs (Heyheaaa I got a new unit)))))

          I should go about the whole problem in another way (Convert values (in units) to Values (in Units) and NOTTTT care what the dialog(or Window) is, and match units for units.

          Only problem is...how do yu convert Dialog Units to pixels? Or Pixels to Dialog Units???

          In the world of "Mr. Owl....the world may never know"
          Engineer's Motto: If it aint broke take it apart and fix it

          "If at 1st you don't succeed... call it version 1.0"

          "Half of Programming is coding"....."The other 90% is DEBUGGING"

          "Document my code????" .... "WHYYY??? do you think they call it CODE? "

          Comment


            #6
            Well, bad memory. It's not "GetDlgBaseUnits", it's "GetDialogBaseUnits"

            And the formula is ..

            Each horizontal base unit is equal to 4 horizontal dialog template units; each vertical base unit is equal to 8 vertical dialog template units. Therefore, to convert dialog template units to pixels, use the following formulas:
            Code:
            pixelX = MulDiv(templateunitX, baseunitX, 4);
            pixelY = MulDiv(templateunitY, baseunitY, 8);
            Similarly, to convert from pixels to dialog template units, use the following formulas:
            Code:
            templateunitX = MulDiv(pixelX, 4, baseunitX);
            templateunitY = MulDiv(pixelY, 8, baseunitY);
            However, in the comments for GetDialogBaseUnits() Ye Olde SDK doc says...

            For either type of dialog box, it is easier to use the MapDialogRect function to perform the conversion. MapDialogRect takes the font into account and correctly converts a rectangle from dialog template units into pixels.
            MCM
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment

            Working...
            X
            😀
            🥰
            🤢
            😎
            😡
            👍
            👎