Jump to content

Multiple Document Interface example


Recommended Posts

I made an example of how to create an MDI application in AutoIt.

I know there is no resizing handling and there are maybe some errors in there, but it works and shows how to do it.

Hope you like it.

Multiple Document Interface example in AutoIt
Author: funkey
Date: 2011, 23rd of September

#include <WinAPIEx.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiMenu.au3>
#include <GuiEdit.au3>

Opt("GUIOnEventMode", 1)

Global Const $IDC_ARROW = 32512
Global Const $tagCLIENTCREATESTRUCT = "HANDLE hWindowMenu;UINT idFirstChild"
Global Const $tagMDICREATESTRUCT = "ptr szClass;ptr szTitle;HANDLE hOwner;int x;int y;int cx;int cy;DWORD style;LPARAM  lParam"

Global Const $CW_USEDEFAULT = 0x80000000
Global Const $IDM_FIRSTCHILD = 50000
Global Const $WM_MDIGETACTIVE = 553
Global Const $WM_MDICREATE = 544
Global Const $WM_MDIACTIVATE = 546
Global Const $WM_MDITILE = 550
Global Const $WM_MDICASCADE = 551
Global Const $MF_ENABLED = 0

Global $hInstance = _WinAPI_GetModuleHandle(0)
Global $hProcChild = DllCallbackRegister('_WndProcChild', 'lresult', 'hwnd;uint;wparam;lparam')
Global $hCursor = _WinAPI_LoadCursor(0, $IDC_ARROW)
Global $tIcon = DllStructCreate('ptr;ptr')
_WinAPI_ExtractIconEx(@SystemDir & '\shell32.dll', 130, DllStructGetPtr($tIcon, 1), DllStructGetPtr($tIcon, 2), 1)
Global $hIcon = DllStructGetData($tIcon, 1)
Global $hIconSm = DllStructGetData($tIcon, 2)

If _MDI_RegisterChildClass() = 0 Then
    ConsoleWrite("Error Registering WindowClass!" & @CRLF)

Global $hGui = GUICreate("AutoIt MDI-Example by funkey", -1, -1, -1, -1, BitOR($WS_MAXIMIZE, $GUI_SS_DEFAULT_GUI))
GUISetOnEvent(-3, "_Exit", $hGui)

Global $filemenu = GUICtrlCreateMenu("&File")
Global $file_new = GUICtrlCreateMenuItem("&New Child", $filemenu)
GUICtrlSetOnEvent(-1, "_NewMDIChild")
Global $file_close = GUICtrlCreateMenuItem("E&xit", $filemenu)
GUICtrlSetOnEvent(-1, "_Exit")

Global $windowmenu = GUICtrlCreateMenu("&Window")
Global $window_tileH = GUICtrlCreateMenuItem("Tile &horizontal", $windowmenu)
GUICtrlSetOnEvent(-1, "_TileH")
Global $window_tileV = GUICtrlCreateMenuItem("Tile &vertical", $windowmenu)
GUICtrlSetOnEvent(-1, "_TileV")
Global $window_cascade = GUICtrlCreateMenuItem("&Cascade", $windowmenu)
GUICtrlSetOnEvent(-1, "_Cascade")

Global $hClient = _MDI_CreateClient($hGui)

GUISetState(@SW_SHOW, $hGui)

Global $hChild = _MDI_CreateChild($hClient, "Untitled 0", "MDIChild")

While 1

Func _TileH()
    _SendMessage($hClient, $WM_MDITILE, 1, 0);
EndFunc   ;==>_TileH

Func _TileV()
    _SendMessage($hClient, $WM_MDITILE, 0, 0);
EndFunc   ;==>_TileV

Func _Cascade()
    _SendMessage($hClient, $WM_MDICASCADE, 0, 0);
EndFunc   ;==>_Cascade

Func _NewMDIChild()
    Static $i = 0
    $i += 1
    _CreateEditOnMDI(_MDI_CreateChild($hClient, "Untitled " & $i, "MDIChild"))
EndFunc   ;==>_NewMDIChild

Func _CreateEditOnMDI($hChild)
    Local $aPos = WinGetClientSize($hChild)
    _GUICtrlEdit_Create($hChild, "", 5, 5, $aPos[0] - 10, $aPos[1] - 10, BitOR($ES_MULTILINE, $ES_WANTRETURN, $ES_AUTOVSCROLL))
EndFunc   ;==>_CreateEditOnMDI

Func _Exit()
EndFunc   ;==>_Exit

Func _WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $hChildMDI
    If $nNotifyCode >= $IDM_FIRSTCHILD Then
        _WinAPI_DefFrameProc($hWnd, $hClient, $WM_COMMAND, $wParam, $lParam)
        $hChildMDI = _SendMessage($hClient, $WM_MDIGETACTIVE, 0, 0, 0, "wparam", "lparam", "hwnd")
        If $hChildMDI Then
            _SendMessage($hChildMDI, $WM_COMMAND, $wParam, $lParam)
    _WinAPI_DefFrameProc($hWnd, $hClient, $WM_COMMAND, $wParam, $lParam)
EndFunc   ;==>_WM_COMMAND

Func _MDI_RegisterChildClass()
    Local $sClass = 'MDIChild'
    Local $tClass = DllStructCreate('wchar[' & StringLen($sClass) + 1 & ']')
    DllStructSetData($tClass, 1, $sClass)

    Local $tWCEX = DllStructCreate($tagWNDCLASSEX)
    DllStructSetData($tWCEX, 'Size', DllStructGetSize($tWCEX))
    DllStructSetData($tWCEX, 'Style', 3)
    DllStructSetData($tWCEX, 'hWndProc', DllCallbackGetPtr($hProcChild))
    DllStructSetData($tWCEX, 'ClsExtra', 0)
    DllStructSetData($tWCEX, 'WndExtra', 0)
    DllStructSetData($tWCEX, 'hInstance', $hInstance)
    DllStructSetData($tWCEX, 'hIcon', $hIcon)
    DllStructSetData($tWCEX, 'hCursor', $hCursor)
    DllStructSetData($tWCEX, 'hBackground', 1);_WinAPI_CreateSolidBrush(_WinAPI_GetSysColor($COLOR_3DFACE)))
    DllStructSetData($tWCEX, 'MenuName', 0)
    DllStructSetData($tWCEX, 'ClassName', DllStructGetPtr($tClass))
    DllStructSetData($tWCEX, 'hIconSm', $hIconSm)
;~  DllStructSetData($tWCEX, 'hIconSm', 0)

    Return _WinAPI_RegisterClassEx($tWCEX)
EndFunc   ;==>_MDI_RegisterChildClass

Func _MDI_CreateClient($hMDIParent)
    Local $aClientSize = WinGetClientSize($hGui)
    Local $iMenuHeight = _WinAPI_GetSystemMetrics(15)
    DllStructSetData($tCLIENTCREATESTRUCT, "hWindowMenu", _GUICtrlMenu_GetItemSubMenu(_GUICtrlMenu_GetMenu($hGui), 1))
    DllStructSetData($tCLIENTCREATESTRUCT, "idFirstChild", $IDM_FIRSTCHILD)

    Local $hMDIClient = _WinAPI_CreateWindowEx( _
            0, "MDICLIENT", "", 0x52000000, _ ;  Fensterstile (WS_CLIPCHILDREN|WS_CHILD|WS_VISIBLE)
            0, 0, $aClientSize[0], $aClientSize[1] - $iMenuHeight, _     ; Position und Grösse des Fensters
            $hMDIParent, 0, $hInstance, _
    Return $hMDIClient
EndFunc   ;==>_MDI_CreateClient

Func _MDI_CreateChild($hMDIClient, $sTitle, $sClassName)
    Local $tClass = DllStructCreate('wchar[' & StringLen($sClassName) + 1 & ']')
    DllStructSetData($tClass, 1, $sClassName)
    Local $tTitle = DllStructCreate('wchar[' & StringLen($sTitle) + 1 & ']')
    DllStructSetData($tTitle, 1, $sTitle)

    DllStructSetData($tMDICREATESTRUCT, 'szClass', DllStructGetPtr($tClass))
    DllStructSetData($tMDICREATESTRUCT, "szTitle", DllStructGetPtr($tTitle))
    DllStructSetData($tMDICREATESTRUCT, "hOwner", $hInstance)
    DllStructSetData($tMDICREATESTRUCT, "style", 0)
    DllStructSetData($tMDICREATESTRUCT, "lParam", 0)

    Local $hRet = _SendMessage($hMDIClient, $WM_MDICREATE, 0, DllStructGetPtr($tMDICREATESTRUCT), 0, "wparam", "lparam", "hwnd")
    Return $hRet
EndFunc   ;==>_MDI_CreateChild

Func _WndProcChild($hWnd, $iMsg, $wParam, $lParam)
    Switch $iMsg
        Case $WM_MDIACTIVATE
            Local $hMenu = _GUICtrlMenu_GetMenu($hGui)
            If $hWnd = HWnd($lParam) Then
                _GUICtrlMenu_EnableMenuItem($hMenu, 1, BitOR($MF_BYPOSITION, $MF_ENABLED))
                _GUICtrlMenu_EnableMenuItem($hMenu, 1, BitOR($MF_BYPOSITION, $MF_GRAYED))
    Return _WinAPI_DefMDIChildProc($hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_WndProcChild

Func _WinAPI_DefMDIChildProc($hWnd, $iMsg, $wParam, $lParam)
    Local $Ret = DllCall('user32.dll', 'lresult', 'DefMDIChildProcW', 'hwnd', $hWnd, 'uint', $iMsg, 'wparam', $wParam, 'lparam', $lParam)
    If @error Then Return SetError(1, 0, 0)
    Return $Ret[0]
EndFunc   ;==>_WinAPI_DefMDIChildProc

Func _WinAPI_DefFrameProc($hWnd, $hWndMDIClient, $iMsg, $wParam, $lParam)
    Local $Ret = DllCall('user32.dll', 'lresult', 'DefFrameProcW', 'hwnd', $hWnd, 'hwnd', $hWndMDIClient, 'uint', $iMsg, 'wparam', $wParam, 'lparam', $lParam)
    If @error Then Return SetError(1, 0, 0)
    Return $Ret[0]
EndFunc   ;==>_WinAPI_DefFrameProc

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

I like it too funkey. :graduated:

When another app is selected the parent window is shown correctly as not focused but the last child window selected is still shown as focused. Can you fix that? I've been trying to do this recently (again) using

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...