Mdi example help

New to FreeBASIC? Post your questions here.
Löwenherz
Posts: 279
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Mdi example help

Post by Löwenherz »

Hello all...

Perhaps Somebody can Help to build a running mdi example with my example . I have Mixed two examples for it. Main Part based on petzolds mdi example... You can Compile example. The Window frame Works. Not more. The menu I have included but Menu Files are still without function..

Code: Select all

.' test mdi demo, part one, loewenherz, 30-10-2024
' freebasic, petzold mdi example as basis
' mixing two mdi examples, but how does petzold example works correct?
'
#Include "windows.bi"
#include once "crt.bi"

Const FILE_EXIT = 1001

type HELLODATA
	as UINT     iColor
	as COLORREF clrText
end type
type PHELLODATA as HELLODATA ptr

'' structure for storing data unique to each Rect child window

type RECTDATA
	as short cxClient
	as short cyClient
end type
type PRECTDATA as RECTDATA ptr

'' global variables
dim shared as string szAppName
szAppName    = "MDIDemo"
dim shared as string szFrameClass
szFrameClass = "MdiFrame"
dim shared as string szHelloClass
szHelloClass = "MdiHelloChild"
dim shared as string szRectClass
szRectClass  = "MdiRectChild"

dim shared as HINSTANCE hInst
dim shared as HMENU hMenuInit, hMenuHello, hMenuRect
dim shared as HMENU hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow

#define IDM_FILE_NEWHELLO               40001
#define IDM_FILE_NEWRECT                40002
#define IDM_APP_EXIT                    40003
#define IDM_FILE_CLOSE                  40004
#define IDM_COLOR_BLACK                 40005
#define IDM_COLOR_RED                   40006
#define IDM_COLOR_GREEN                 40007
#define IDM_COLOR_BLUE                  40008
#define IDM_COLOR_WHITE                 40009
#define IDM_WINDOW_CASCADE              40010
#define IDM_WINDOW_TILE                 40011
#define IDM_WINDOW_ARRANGE              40012
#define IDM_WINDOW_CLOSEALL             40013

Const FILE_EXIT = 1001
Dim As MSG msg
Dim shared As HWND hWnd, hMDIClient, hwMDI

Dim  wc As wndclassex

#define INIT_MENU_POS    0
#define HELLO_MENU_POS   2
#define RECT_MENU_POS    1

#define IDM_FIRSTCHILD   50000

Declare function WndProc(hDlg as hwnd,Msg as uint,wparam as wparam,lparam as lparam) as Integer
Declare function ChildWndProc(hDlg as hwnd,Msg as uint,wparam as wparam,lparam as lparam) as Integer
declare function  HelloWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

Declare function CloseEnumProc (byval hwnd as HWND, byval lParam as LPARAM) as BOOL
Declare function RectWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

With wc
.cbSize = SIZEOF( WNDCLASSEX )
.style = CS_HREDRAW or CS_VREDRAW 
.lpfnWndProc = @WndProc
.cbClsExtra = NULL 
.cbWndExtra = NULL
.hInstance =GetModuleHandle(0)
.hbrBackground =Cast(HBRUSH,28)
.lpszMenuName = NULL
.lpszClassName = @"Simple"
.hIcon = LoadIcon( NULL,IDI_APPLICATION )
.hIconSm = .hIcon
.hCursor = LoadCursor( NULL,IDC_ARROW)
end With


if(RegisterClassEx(@wc) = FALSE) then
MessageBox(0,"Can not register window class","Error",0)
end 1
end If

With wc
.cbSize = SIZEOF( WNDCLASSEX )
.style = CS_HREDRAW or CS_VREDRAW 
.lpfnWndProc = @ChildWndProc
.cbClsExtra = NULL 
.cbWndExtra = NULL
.hInstance =GetModuleHandle(0)
.hbrBackground =Cast(HBRUSH,28)
.lpszMenuName = NULL
.lpszClassName = @"SimpleChild"
.hIcon = LoadIcon( NULL,IDI_APPLICATION )
.hIconSm = .hIcon
.hCursor = LoadCursor( NULL,IDC_ARROW)
end With

With wc
.cbSize = SIZEOF( WNDCLASSEX )
.style = CS_HREDRAW or CS_VREDRAW 
.lpfnWndProc = @HelloWndProc
.cbClsExtra = NULL 
.cbWndExtra = NULL
.hInstance =GetModuleHandle(0)
.hbrBackground =Cast(HBRUSH,28)
.lpszMenuName = NULL
.lpszClassName = @"szHelloClass"
.hIcon = LoadIcon( NULL,IDI_APPLICATION )
.hIconSm = .hIcon
.hCursor = LoadCursor( NULL,IDC_ARROW)
end With

With wc
.cbSize = SIZEOF( WNDCLASSEX )
.style = CS_HREDRAW or CS_VREDRAW 
.lpfnWndProc = @RectWndProc
.cbClsExtra = NULL 
.cbWndExtra = NULL
.hInstance =GetModuleHandle(0)
.hbrBackground =Cast(HBRUSH,28)
.lpszMenuName = NULL
.lpszClassName = @"szRectClass"
.hIcon = LoadIcon( NULL,IDI_APPLICATION )
.hIconSm = .hIcon
.hCursor = LoadCursor( NULL,IDC_ARROW)
end With

if(RegisterClassEx(@wc) = FALSE) then
MessageBox(0,"Can not register window class","Error",0)
end 1
end If

' not petzold 
Function WndProc(hDlg as hwnd,Msg as uint,wparam as wparam,lparam as lparam) as integer
        select case msg
        case wm_create
            Dim as HMENU Menu = CreateMenu
            Dim as HMENU subWindows = CreatePopupMenu 'subMenu
            'AppendMenu Menu, MF_POPUP OR MF_ENABLED, subWindows, "&File"
            
            Menu = CreateMenu
            AppendMenu(subWindows,MF_STRING,100,"Cascade")
            AppendMenu(subWindows,MF_STRING,100,"Tile")
            AppendMenu(subWindows,MF_STRING,100,"Arrange")
            AppendMenu(subWindows,MF_STRING,FILE_EXIT,"Exit")
            
            AppendMenu(Menu,MF_POPUP,Cint(subWindows),"Windows")
            
            DrawMenuBar(hDlg)
            SetMenu(hDlg,Menu)
            
            Dim as HMENU hMenuWindow = CreatePopUpMenu
            
            AppendMenu(hMenuWindow,MF_STRING,101,"NewHello")
            AppendMenu(hMenuWindow,MF_STRING,101,"NewRectangle")
            AppendMenu(hMenuWindow, MF_SEPARATOR, 0, "") 'hSubMenu 
            
            'AppendMenu(subWindows,MF_STRING,FILE_EXIT,"Exit")
            AppendMenu(Menu,MF_POPUP,CInt(hMenuWindow),"File")
            
            DrawMenuBar(hDlg)
            SetMenu(hDlg,Menu)
            
            Dim as HMENU hMenuCol = CreatePopUpMenu
            
            AppendMenu(hMenuCol,MF_STRING,102,"Black")
            AppendMenu(hMenuCol,MF_STRING,102,"Red")
            AppendMenu(hMenuCol,MF_STRING,102,"Green")
            AppendMenu(hMenuCol,MF_STRING,102,"Blue")
            AppendMenu(hMenuCol,MF_STRING,102,"White")
            AppendMenu(Menu,MF_POPUP,CInt(hMenuCol),"Colors")
            
            'AppendMenu(hMenuCol, MF_SEPARATOR, 0, "") 'hSubMenu 
            DrawMenuBar(hDlg)
            SetMenu(hDlg,Menu)
            
            Dim As CLIENTCREATESTRUCT ccs
            ccs.hWindowMenu = subWindows
            ccs.idFirstChild = &HFF000
            hMDIClient = CreateWindow("MDICLIENT", "",WS_CHILD Or WS_CLIPCHILDREN Or WS_CLIPSIBLINGS Or WS_VISIBLE Or WS_VSCROLL Or WS_HSCROLL,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hDlg,Cast(HMENU,&HCAC),GetModuleHandle(0),@ccs)
            hwMDI = CreateWindowEx(WS_EX_MDICHILD, "SimpleChild", "", WS_OVERLAPPEDWINDOW Or WS_VISIBLE, CW_USEDEFAULT,CW_USEDEFAULT,300,200,hMDIClient, 0, GetModuleHandle(0),0)
            Return false
        
        case FILE_EXIT
				PostMessage( hWnd, WM_CLOSE, 0, 0 )
				exit function
'			end select
			
        case wm_close
            PostQuitMessage(0)
        end select
        return DefFrameProc(hDlg, hMDIClient, Msg, wParam, lParam)
End function

' not petzold 
function ChildWndProc(hDlg as hwnd,Msg as uint,wparam as wparam,lparam as lparam) as integer
        select case msg
        case wm_close
            select case MessageBox(hDlg,"Close ?","MDIChild",mb_iconquestion or mb_yesno)
            case idno 
                return true
            end select
        end select
        return DefMDIChildProc(hDlg, Msg, wParam, lParam)
End function

hWnd = CreateWindowEx( 0, "Simple", "Hello MDI Example", WS_OVERLAPPEDWINDOW Or WS_VISIBLE Or WS_CLIPCHILDREN Or WS_CLIPSIBLINGS, 100, 100, 500, 300, 0, 0, GetModuleHandle(0), 0 )

While GetMessage( @msg, 0, 0, 0 )
        TranslateMessage( @msg )
        DispatchMessage( @msg )
Wend

' petzold
function CloseEnumProc (byval hwnd as HWND, byval lParam as LPARAM) as BOOL

	if (GetWindow (hwnd, GW_OWNER) <> 0) then         '' Check for icon title
		return TRUE
	end if
	SendMessage (GetParent (hwnd), WM_MDIRESTORE, cast(WPARAM, hwnd), 0)

	if (SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0) = 0) then return TRUE

	SendMessage (GetParent (hwnd), WM_MDIDESTROY, cast(WPARAM, hwnd), 0)
	return TRUE
end function


' petzold
function  HelloWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

static as COLORREF clrTextArray(0 to 4) => _
          { rgb (0, 0, 0), _
            rgb (0, 0, 255), _
            rgb (0, 255, 0), _
            rgb (255, 0, 0), _
            rgb (255, 255, 255) }

	static as HWND hwndClient, hwndFrame
	dim as HDC hdc
	dim as HMENU hMenu
	dim as PHELLODATA pHelloData
	dim as PAINTSTRUCT ps
	dim as RECT rect

	select case (message)
	case WM_CREATE:
		'' Allocate memory for window private data

		pHelloData = cast(PHELLODATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, sizeof (HELLODATA)))
		pHelloData->iColor  = IDM_COLOR_BLACK
		pHelloData->clrText = rgb (0, 0, 0)
		SetWindowLong (hwnd, 0, cast(long, pHelloData))

		'' Save some window handles

		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		return 0

	case WM_COMMAND
		select case (LOWORD (wParam))
		case IDM_COLOR_BLACK, IDM_COLOR_RED, IDM_COLOR_GREEN, IDM_COLOR_BLUE, IDM_COLOR_WHITE
			'' Change the text color

			pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))

			hMenu = GetMenu (hwndFrame)

			CheckMenuItem (hMenu, pHelloData->iColor, MF_UNCHECKED)
			pHelloData->iColor = wParam
			CheckMenuItem (hMenu, pHelloData->iColor, MF_CHECKED)

			pHelloData->clrText = clrTextArray(wParam - IDM_COLOR_BLACK)

			InvalidateRect (hwnd, NULL, FALSE)
		end select
		return 0

	case WM_PAINT
		'' Paint the window

		hdc = BeginPaint (hwnd, @ps)

		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		SetTextColor (hdc, pHelloData->clrText)

		GetClientRect (hwnd, @rect)

		DrawText (hdc, "Hello, World!", -1, @rect, _
			DT_SINGLELINE or DT_CENTER or DT_VCENTER)

		EndPaint (hwnd, @ps)
		return 0

	case WM_MDIACTIVATE
		'' Set the Hello menu if gaining focus

		if (lParam = cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, _
				cast(WPARAM, hMenuHello), cast(LPARAM, hMenuHelloWindow))
		end if
		'' Check or uncheck menu item

		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		CheckMenuItem (hMenuHello, pHelloData->iColor, _
			(iif(lParam = cast(LPARAM, hwnd), MF_CHECKED, MF_UNCHECKED)))

		'' Set the Init menu if losing focus

		if (lParam <> cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuInit), _
				cast(LPARAM, hMenuInitWindow))
		end if
		DrawMenuBar (hwndFrame)
		return 0

	case WM_QUERYENDSESSION, WM_CLOSE
		if (IDOK <> MessageBox (hwnd, "OK to close window?", _
				"Hello", _
				MB_ICONQUESTION or MB_OKCANCEL)) then return 0

		''else process by DefMDIChildProc

	case WM_DESTROY
		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pHelloData)
		return 0
	end select
	'' Pass unprocessed message to DefMDIChildProc

	return DefMDIChildProc (hwnd, message, wParam, lParam)
end function

' petzold       
function RectWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as HWND hwndClient, hwndFrame
	dim as HBRUSH      hBrush
	dim as HDC         hdc
	dim as PRECTDATA   pRectData
	dim as PAINTSTRUCT ps
	dim as integer         xLeft, xRight, yTop, yBottom
	dim as short       nRed, nGreen, nBlue

	select case message
	case WM_CREATE
		'' Allocate memory for window private data

		pRectData = cast(PRECTDATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, sizeof (RECTDATA)))

		SetWindowLong (hwnd, 0, cast(long, pRectData))

		'' Start the timer going

		SetTimer (hwnd, 1, 250, NULL)

		'' Save some window handles
		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		return 0

	case WM_SIZE             '' If not minimized, save the window size

		if (wParam <> SIZE_MINIMIZED) then
			pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))

			pRectData->cxClient = LOWORD (lParam)
			pRectData->cyClient = hiword (lParam)
		end if

		'' WM_SIZE must be processed by DefMDIChildProc (no return 0)

	case WM_TIMER            '' Display a random rectangle

		pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))
		xLeft   = rand () mod pRectData->cxClient
		xRight  = rand () mod pRectData->cxClient
		yTop    = rand () mod pRectData->cyClient
		yBottom = rand () mod pRectData->cyClient
		nRed    = rand () and 255
		nGreen  = rand () and 255
		nBlue   = rand () and 255

		hdc = GetDC (hwnd)
		hBrush = CreateSolidBrush (rgb (nRed, nGreen, nBlue))
		SelectObject (hdc, hBrush)

		Rectangle (hdc, min (xLeft, xRight), min (yTop, yBottom), _
			max (xLeft, xRight), max (yTop, yBottom))

		ReleaseDC (hwnd, hdc)
		DeleteObject (hBrush)
		return 0

	case WM_PAINT            '' Clear the window

		InvalidateRect (hwnd, NULL, TRUE)
		hdc = BeginPaint (hwnd, @ps)
		EndPaint (hwnd, @ps)
		return 0

	case WM_MDIACTIVATE      '' Set the appropriate menu
		if (lParam = cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuRect), _
				cast(LPARAM, hMenuRectWindow))
		else
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuInit), _
				cast(LPARAM, hMenuInitWindow))
		end if
		DrawMenuBar (hwndFrame)
		return 0

	case WM_DESTROY
		pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pRectData)
		KillTimer (hwnd, 1)
		return 0
	end select

	'' Pass unprocessed message to DefMDIChildProc
	return DefMDIChildProc (hwnd, message, wParam, lParam)
end function
'ends

SARG
Posts: 1888
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Mdi example help

Post by SARG »

Not searching a lot but why do you want to change/cast a long (data) to a pointer (pHelloData) ?
I guess that you have to begin here to solve your issue.

I have not the time for now to go deeper :-)
paul doe
Posts: 1878
Joined: Jul 25, 2017 17:22
Location: Argentina
Contact:

Re: Mdi example help

Post by paul doe »

Main Part based on petzolds mdi example...
You know, it would be really, really handy if you could provide a link to your citations whenever you seek help. You can't reasonably expect people to know what you're talking about, that they have come across the example you mention, or that they're required to waste their time looking up the citations themselves. Being considerate goes a long way into quickly getting the answers you're seeking, without having to fumble around with no context whatsoever.
Löwenherz
Posts: 279
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Mdi example help

Post by Löwenherz »

You know, it would be really, really handy if you could provide a link to your citations whenever you seek help. You can't reasonably expect people to know what you're talking about, that they have come across the example you mention, or that they're required to waste their time looking up the citations themselves. Being considerate goes a long way into quickly getting the answers you're seeking, without having to fumble around with no context whatsoever.

Here's Petzold example from 1998 with RC File. But my Intention was to make this mdi example with No Ressource File and all Features in one example... To understand I have startet a simple frame with mdi and menues.. then I tried to Mix IT cause ti prevent the Ressource File...

Code: Select all

'mdidemo.bas
'

''--------------------------------------------------------
''   MDIDEMO.C -- Multiple-Document Interface Demonstration
''                (c) Charles Petzold, 1998
''--------------------------------------------------------
''
'' Compile:  fbc mdidemo.bas mdidemo.rc
''

#define NULL 0

#include once "windows.bi"
#include once "crt.bi"

#define IDM_FILE_NEWHELLO               40001
#define IDM_FILE_NEWRECT                40002
#define IDM_APP_EXIT                    40003
#define IDM_FILE_CLOSE                  40004
#define IDM_COLOR_BLACK                 40005
#define IDM_COLOR_RED                   40006
#define IDM_COLOR_GREEN                 40007
#define IDM_COLOR_BLUE                  40008
#define IDM_COLOR_WHITE                 40009
#define IDM_WINDOW_CASCADE              40010
#define IDM_WINDOW_TILE                 40011
#define IDM_WINDOW_ARRANGE              40012
#define IDM_WINDOW_CLOSEALL             40013


#define INIT_MENU_POS    0
#define HELLO_MENU_POS   2
#define RECT_MENU_POS    1

#define IDM_FIRSTCHILD   50000



'' Note: CALLBACK = WINAPI = stdcall, which is the default in freebasic
declare function WinMain (byval hInstance as HINSTANCE, _
	byval hPrevInstance as HINSTANCE, _
	byval szCmdLine as string, _
	byval iCmdShow as integer) as integer
declare function FrameWndProc (byval hwnd as HWND, byval message as UINT, _
	byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
declare function CloseEnumProc (byval hwnd as HWND, byval lParam as LPARAM) as BOOL
declare function  HelloWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
declare function RectWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

'' structure for storing data unique to each Hello child window

type HELLODATA
	as UINT     iColor
	as COLORREF clrText
end type
type PHELLODATA as HELLODATA ptr

'' structure for storing data unique to each Rect child window

type RECTDATA
	as short cxClient
	as short cyClient
end type
type PRECTDATA as RECTDATA ptr

'' global variables
dim shared as string szAppName
szAppName    = "MDIDemo"
dim shared as string szFrameClass
szFrameClass = "MdiFrame"
dim shared as string szHelloClass
szHelloClass = "MdiHelloChild"
dim shared as string szRectClass
szRectClass  = "MdiRectChild"

dim shared as HINSTANCE hInst
dim shared as HMENU hMenuInit, hMenuHello, hMenuRect
dim shared as HMENU hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow


end WinMain( GetModuleHandle( null ), null, command( ), SW_NORMAL )

function WinMain (byval hInstance as HINSTANCE, _
		byval hPrevInstance as HINSTANCE, _
		byval szCmdLine as string, _
		byval iCmdShow as integer) as integer

	dim as HACCEL   hAccel
	dim as HWND     hwndFrame, hwndClient
	dim as MSG      msg
	dim as WNDCLASS wndclass

	hInst = hInstance

	'' Register the frame window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @FrameWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = 0
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast(HBRUSH, (COLOR_APPWORKSPACE + 1))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szFrameClass)

	if RegisterClass (@wndclass) = 0 then
		MessageBox (NULL, "This program requires Windows!", _
			szAppName, MB_ICONERROR)
		return 0
	end if

	'' Register the Hello child window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @HelloWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = sizeof (HANDLE)
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast(HBRUSH, GetStockObject (WHITE_BRUSH))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szHelloClass)

	RegisterClass (@wndclass)

	'' Register the Rect child window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @RectWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = sizeof (HANDLE)
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast (HBRUSH, GetStockObject (WHITE_BRUSH))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szRectClass)

	RegisterClass (@wndclass)

	'' Obtain handles to three possible menus & submenus

	hMenuInit  = LoadMenu (hInstance, "MdiMenuInit")
	hMenuHello = LoadMenu (hInstance, "MdiMenuHello")
	hMenuRect  = LoadMenu (hInstance, "MdiMenuRect")

	hMenuInitWindow  = GetSubMenu (hMenuInit,   INIT_MENU_POS)
	hMenuHelloWindow = GetSubMenu (hMenuHello, HELLO_MENU_POS)
	hMenuRectWindow  = GetSubMenu (hMenuRect,   RECT_MENU_POS)

	'' Load accelerator table

	hAccel = LoadAccelerators (hInstance, szAppName)

	'' Create the frame window

	hwndFrame = CreateWindow (szFrameClass, "MDI Demonstration", _
		WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN, _
		CW_USEDEFAULT, CW_USEDEFAULT, _
		CW_USEDEFAULT, CW_USEDEFAULT, _
		NULL, hMenuInit, hInstance, NULL)
	hwndClient = GetWindow (hwndFrame, GW_CHILD)

	ShowWindow (hwndFrame, iCmdShow)
	UpdateWindow (hwndFrame)

	'' Enter the modified message loop

	while (GetMessage (@msg, NULL, 0, 0))
		if (TranslateMDISysAccel (hwndClient, @msg) = 0) and  _
				(TranslateAccelerator (hwndFrame, hAccel, @msg) = 0) then
			TranslateMessage (@msg)
			DispatchMessage (@msg)
		end if
	wend
	'' Clean up by deleting unattached menus

	DestroyMenu (hMenuHello)
	DestroyMenu (hMenuRect)

	return msg.wParam
end function

function FrameWndProc (byval hwnd as HWND, byval message as UINT, _
		byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as HWND hwndClient
	dim as CLIENTCREATESTRUCT clientcreate
	dim as HWND hwndChild
	dim as MDICREATESTRUCT mdicreate

	select case message
	case WM_CREATE           '' Create the client window

		clientcreate.hWindowMenu  = hMenuInitWindow
		clientcreate.idFirstChild = IDM_FIRSTCHILD

		hwndClient = CreateWindow ("MDICLIENT", NULL, _
			WS_CHILD or WS_CLIPCHILDREN or WS_VISIBLE, _
			0, 0, 0, 0, hwnd, cast(HMENU, 1), hInst, _
			cast (PSTR, @clientcreate))
		return 0

	case WM_COMMAND
		select case (LOWORD (wParam))
		case IDM_FILE_NEWHELLO       '' Create a Hello child window

			mdicreate.szClass = strptr(szHelloClass)
			mdicreate.szTitle = @"Hello"
			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 = cast(HWND, SendMessage (hwndClient, _
				WM_MDICREATE, 0, _
				cast(LPARAM,@mdicreate)))
			return 0

		case IDM_FILE_NEWRECT        '' Create a Rect child window

			mdicreate.szClass = strptr(szRectClass)
			mdicreate.szTitle = @"Rectangles"
			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 = cast(HWND, SendMessage (hwndClient, _
				WM_MDICREATE, 0, _
				cast(LPARAM, @mdicreate)))
			return 0

		case IDM_FILE_CLOSE          '' Close the active window

			hwndChild = cast(HWND, SendMessage (hwndClient, _
				WM_MDIGETACTIVE, 0, 0))

			if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0) <> 0) then _
				SendMessage (hwndClient, WM_MDIDESTROY, _
				cast(WPARAM, hwndChild), 0)
			return 0
		case IDM_APP_EXIT            '' Exit the program

			SendMessage (hwnd, WM_CLOSE, 0, 0)
			return 0

			'' messages for arranging windows

		case IDM_WINDOW_TILE
			SendMessage (hwndClient, WM_MDITILE, 0, 0)
			return 0

		case IDM_WINDOW_CASCADE
			SendMessage (hwndClient, WM_MDICASCADE, 0, 0)
			return 0

		case IDM_WINDOW_ARRANGE
			SendMessage (hwndClient, WM_MDIICONARRANGE, 0, 0)
			return 0

		case IDM_WINDOW_CLOSEALL     '' Attempt to close all children
			EnumChildWindows (hwndClient, @CloseEnumProc, 0)
			return 0

		case else             '' Pass to active child...

			hwndChild = cast(HWND, SendMessage (hwndClient, _
				WM_MDIGETACTIVE, 0, 0))
			if (IsWindow (hwndChild)) then
				SendMessage (hwndChild, WM_COMMAND, wParam, lParam)
			end if
		end select

	case WM_QUERYENDSESSION, WM_CLOSE                      '' Attempt to close all children

		SendMessage (hwnd, WM_COMMAND, IDM_WINDOW_CLOSEALL, 0)

		if (NULL <> GetWindow (hwndClient, GW_CHILD)) then return 0

	case WM_DESTROY
		PostQuitMessage (0)
		return 0
	end select

	'' Pass unprocessed messages to DefFrameProc (not DefWindowProc)
	return DefFrameProc (hwnd, hwndClient, message, wParam, lParam)
end function

function CloseEnumProc (byval hwnd as HWND, byval lParam as LPARAM) as BOOL

	if (GetWindow (hwnd, GW_OWNER) <> 0) then         '' Check for icon title
		return TRUE
	end if
	SendMessage (GetParent (hwnd), WM_MDIRESTORE, cast(WPARAM, hwnd), 0)

	if (SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0) = 0) then return TRUE

	SendMessage (GetParent (hwnd), WM_MDIDESTROY, cast(WPARAM, hwnd), 0)
	return TRUE
end function

function  HelloWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as COLORREF clrTextArray(0 to 4) => _
          { rgb (0, 0, 0), _
            rgb (0, 0, 255), _
            rgb (0, 255, 0), _
            rgb (255, 0, 0), _
            rgb (255, 255, 255) }

	static as HWND hwndClient, hwndFrame
	dim as HDC hdc
	dim as HMENU hMenu
	dim as PHELLODATA pHelloData
	dim as PAINTSTRUCT ps
	dim as RECT rect

	select case (message)
	case WM_CREATE:
		'' Allocate memory for window private data

		pHelloData = cast(PHELLODATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, sizeof (HELLODATA)))
		pHelloData->iColor  = IDM_COLOR_BLACK
		pHelloData->clrText = rgb (0, 0, 0)
		SetWindowLong (hwnd, 0, cast(long, pHelloData))

		'' Save some window handles

		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		return 0

	case WM_COMMAND
		select case (LOWORD (wParam))
		case IDM_COLOR_BLACK, IDM_COLOR_RED, IDM_COLOR_GREEN, IDM_COLOR_BLUE, IDM_COLOR_WHITE
			'' Change the text color

			pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))

			hMenu = GetMenu (hwndFrame)

			CheckMenuItem (hMenu, pHelloData->iColor, MF_UNCHECKED)
			pHelloData->iColor = wParam
			CheckMenuItem (hMenu, pHelloData->iColor, MF_CHECKED)

			pHelloData->clrText = clrTextArray(wParam - IDM_COLOR_BLACK)

			InvalidateRect (hwnd, NULL, FALSE)
		end select
		return 0

	case WM_PAINT
		'' Paint the window

		hdc = BeginPaint (hwnd, @ps)

		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		SetTextColor (hdc, pHelloData->clrText)

		GetClientRect (hwnd, @rect)

		DrawText (hdc, "Hello, World!", -1, @rect, _
			DT_SINGLELINE or DT_CENTER or DT_VCENTER)

		EndPaint (hwnd, @ps)
		return 0

	case WM_MDIACTIVATE
		'' Set the Hello menu if gaining focus

		if (lParam = cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, _
				cast(WPARAM, hMenuHello), cast(LPARAM, hMenuHelloWindow))
		end if
		'' Check or uncheck menu item

		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		CheckMenuItem (hMenuHello, pHelloData->iColor, _
			(iif(lParam = cast(LPARAM, hwnd), MF_CHECKED, MF_UNCHECKED)))

		'' Set the Init menu if losing focus

		if (lParam <> cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuInit), _
				cast(LPARAM, hMenuInitWindow))
		end if
		DrawMenuBar (hwndFrame)
		return 0

	case WM_QUERYENDSESSION, WM_CLOSE
		if (IDOK <> MessageBox (hwnd, "OK to close window?", _
				"Hello", _
				MB_ICONQUESTION or MB_OKCANCEL)) then return 0

		''else process by DefMDIChildProc

	case WM_DESTROY
		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pHelloData)
		return 0
	end select
	'' Pass unprocessed message to DefMDIChildProc

	return DefMDIChildProc (hwnd, message, wParam, lParam)
end function


function RectWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as HWND hwndClient, hwndFrame
	dim as HBRUSH      hBrush
	dim as HDC         hdc
	dim as PRECTDATA   pRectData
	dim as PAINTSTRUCT ps
	dim as integer         xLeft, xRight, yTop, yBottom
	dim as short       nRed, nGreen, nBlue

	select case message
	case WM_CREATE
		'' Allocate memory for window private data

		pRectData = cast(PRECTDATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, sizeof (RECTDATA)))

		SetWindowLong (hwnd, 0, cast(long, pRectData))

		'' Start the timer going

		SetTimer (hwnd, 1, 250, NULL)

		'' Save some window handles
		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		return 0

	case WM_SIZE             '' If not minimized, save the window size

		if (wParam <> SIZE_MINIMIZED) then
			pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))

			pRectData->cxClient = LOWORD (lParam)
			pRectData->cyClient = hiword (lParam)
		end if

		'' WM_SIZE must be processed by DefMDIChildProc (no return 0)

	case WM_TIMER            '' Display a random rectangle

		pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))
		xLeft   = rand () mod pRectData->cxClient
		xRight  = rand () mod pRectData->cxClient
		yTop    = rand () mod pRectData->cyClient
		yBottom = rand () mod pRectData->cyClient
		nRed    = rand () and 255
		nGreen  = rand () and 255
		nBlue   = rand () and 255

		hdc = GetDC (hwnd)
		hBrush = CreateSolidBrush (rgb (nRed, nGreen, nBlue))
		SelectObject (hdc, hBrush)

		Rectangle (hdc, min (xLeft, xRight), min (yTop, yBottom), _
			max (xLeft, xRight), max (yTop, yBottom))

		ReleaseDC (hwnd, hdc)
		DeleteObject (hBrush)
		return 0

	case WM_PAINT            '' Clear the window

		InvalidateRect (hwnd, NULL, TRUE)
		hdc = BeginPaint (hwnd, @ps)
		EndPaint (hwnd, @ps)
		return 0

	case WM_MDIACTIVATE      '' Set the appropriate menu
		if (lParam = cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuRect), _
				cast(LPARAM, hMenuRectWindow))
		else
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuInit), _
				cast(LPARAM, hMenuInitWindow))
		end if
		DrawMenuBar (hwndFrame)
		return 0

	case WM_DESTROY
		pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pRectData)
		KillTimer (hwnd, 1)
		return 0
	end select

	'' Pass unprocessed message to DefMDIChildProc
	return DefMDIChildProc (hwnd, message, wParam, lParam)
end function

'mdidemo.rc
'

//Microsoft Developer Studio generated resource script.
// Microsoft Developer Studio generated include file.
// Used by MDIDemo.rc


#define IDM_FILE_NEWHELLO               40001
#define IDM_FILE_NEWRECT                40002
#define IDM_APP_EXIT                    40003
#define IDM_FILE_CLOSE                  40004
#define IDM_COLOR_BLACK                 40005
#define IDM_COLOR_RED                   40006
#define IDM_COLOR_GREEN                 40007
#define IDM_COLOR_BLUE                  40008
#define IDM_COLOR_WHITE                 40009
#define IDM_WINDOW_CASCADE              40010
#define IDM_WINDOW_TILE                 40011
#define IDM_WINDOW_ARRANGE              40012
#define IDM_WINDOW_CLOSEALL             40013

//#include "resource.h"
//#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
// Menu

MDIMENUINIT MENU DISCARDABLE
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "New &Hello",                  IDM_FILE_NEWHELLO
        MENUITEM "New &Rectangle",              IDM_FILE_NEWRECT
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       IDM_APP_EXIT
    END
END

MDIMENUHELLO MENU DISCARDABLE
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "New &Hello",                  IDM_FILE_NEWHELLO
        MENUITEM "New &Rectangle",              IDM_FILE_NEWRECT
        MENUITEM "&Close",                      IDM_FILE_CLOSE
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       IDM_APP_EXIT
    END
    POPUP "&Color"
    BEGIN
        MENUITEM "&Black",                      IDM_COLOR_BLACK
        MENUITEM "&Red",                        IDM_COLOR_RED
        MENUITEM "&Green",                      IDM_COLOR_GREEN
        MENUITEM "B&lue",                       IDM_COLOR_BLUE
        MENUITEM "&White",                      IDM_COLOR_WHITE
    END
    POPUP "&Window"
    BEGIN
        MENUITEM "&Cascade\tShift+F5",          IDM_WINDOW_CASCADE
        MENUITEM "&Tile\tShift+F4",             IDM_WINDOW_TILE
        MENUITEM "Arrange &Icons",              IDM_WINDOW_ARRANGE
        MENUITEM "Close &All",                  IDM_WINDOW_CLOSEALL
    END
END

MDIMENURECT MENU DISCARDABLE
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "New &Hello",                  IDM_FILE_NEWHELLO
        MENUITEM "New &Rectangle",              IDM_FILE_NEWRECT
        MENUITEM "&Close",                      IDM_FILE_CLOSE
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       IDM_APP_EXIT
    END
    POPUP "&Window"
    BEGIN
        MENUITEM "&Cascade\tShift+F5",          IDM_WINDOW_CASCADE
        MENUITEM "&Tile\tShift+F4",             IDM_WINDOW_TILE
        MENUITEM "Arrange &Icons",              IDM_WINDOW_ARRANGE
        MENUITEM "Close &All",                  IDM_WINDOW_CLOSEALL
    END
END

/////////////////////////////////////////////////////////////////////////////
// Accelerator

MDIDEMO ACCELERATORS DISCARDABLE
BEGIN
    VK_F4,          IDM_WINDOW_TILE,        VIRTKEY, SHIFT, NOINVERT
    VK_F5,          IDM_WINDOW_CASCADE,     VIRTKEY, SHIFT, NOINVERT
END
I supposed there are Not so many freebasic user they are working with winapi SDK Style but I want to learn more how thats working with freebasic.. except Jose rocas afx mdi example I havent found another fully running example at the board
SARG
Posts: 1888
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Mdi example help

Post by SARG »

Löwenherz wrote: Oct 30, 2024 15:48 I supposed there are Not so many freebasic user they are working with winapi SDK Style
I did. Now using Window9 library but I can help you.
Löwenherz wrote: Oct 30, 2024 14:01 The menu I have included but Menu Files are still without function..
Not sure to understand : you want to say that the menu is not working ?
In your code nothing is used to handle the selection of an option.
By the way you use the same identifier (eg 100) for different options so only one option will be selected whatever the choice.

And your code can't work on 64bit : GetWindowLongPtr must be used. On 32bit at compilation time it will normally be replaced by a call to GetWindowLong.
Löwenherz
Posts: 279
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Mdi example help

Post by Löwenherz »

Thanks fir Feedback Sarg.. I am still at Work and have Not enough time to Check more.. tomorrow I will make a complete new Setup for my mdi example.. I guess I now the direction already

I am at Home working with 32 and 64 bit bit machines. The example I have used and tried First however is 32bit old .. See you thx so far Löwenherz
Löwenherz
Posts: 279
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Mdi example help

Post by Löwenherz »

Hello Sarg..
Here WE Go I have found a solution for my mdi example. If you Compile the File you will get a Windows frame with Name mdi Demonstration.. and a Menu with Windows and File. If you click File Menu opens a new submenu with newhello and newrectangle. Test IT you will See :-)

If you click later for example Windows Menü "tile" so Windows get tiled for example the Hello Windows ..in two parts .. some little corrections will come I suppose and I cant Imagine its perfect

Code: Select all

' mdi example, update part two, freebasic, loewenherz
' 30-10-2024, GO :-)
'
#Include "windows.bi"
'#include once "crt.bi"

Dim Shared As HINSTANCE hInst 

Declare Function WndProc(hDlg as hwnd,Msg as uint,wparam as wparam,lparam as lparam) as LRESULT  
Declare function CloseEnumProc (byval hwnd as HWND, byval lParam as LPARAM) as BOOL
Declare function RectWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
declare function  HelloWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

Dim Shared As HWND hWndMDIClient 

'#define IDM_FILE_NEWHELLO 4001
#Define IDM_FILE_NEWHELLO    40001  
#Define IDM_FILE_NEWRECT     40002
#Define IDM_APP_EXIT         40003
#Define IDM_FILE_CLOSE       40004
#Define IDM_COLOR_BLACK      40005
#Define IDM_COLOR_RED        40006
#Define IDM_COLOR_GREEN      40007
#Define IDM_COLOR_BLUE       40008
#Define IDM_COLOR_WHITE      40009
#Define IDM_WINDOW_CASCADE   40010
#Define IDM_WINDOW_TILE      40011
#Define IDM_WINDOW_ARRANGE   40012
#Define IDM_WINDOW_CLOSEALL  40013

#Define INIT_MENU_POS    0
#Define HELLO_MENU_POS   2
#Define RECT_MENU_POS    1

#Define IDM_FIRSTCHILD   50000
#Define IDM_FILE_EXIT    50001

type HELLODATA
	as UINT     iColor
	as COLORREF clrText
end type
type PHELLODATA as HELLODATA ptr

'' structure for storing data unique to each Rect child window

type RECTDATA
	as short cxClient
	as short cyClient
end type
type PRECTDATA as RECTDATA ptr


'' global variables
dim shared as string szAppName
szAppName    = "MDIDemo"
dim shared as string szFrameClass
szFrameClass = "MdiFrame"
dim shared as string szHelloClass
szHelloClass = "MdiHelloChild"
dim shared as string szRectClass
szRectClass  = "MdiRectChild"

'dim shared as HINSTANCE hInst
dim shared as HMENU hMenuInit, hMenuHello, hMenuRect
dim shared as HMENU hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow


function WinMain (byval hInstance as HINSTANCE, _
		byval hPrevInstance as HINSTANCE, _
		byval szCmdLine as string, _
		byval iCmdShow as integer) as integer

	dim as HACCEL   hAccel
	dim as HWND     hwndFrame, hwndClient
	dim as MSG      msg
	dim as WNDCLASS wndclass

	hInst = hInstance

	'' Register the frame window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @WndProc 
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = 0
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast(HBRUSH, (COLOR_APPWORKSPACE + 1))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szFrameClass)

	if RegisterClass (@wndclass) = 0 then
		MessageBox (NULL, "This program requires Windows!", _
			szAppName, MB_ICONERROR)
		return 0
	end if

	'' Register the Hello child window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @HelloWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = sizeof (HANDLE)
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast(HBRUSH, GetStockObject (WHITE_BRUSH))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szHelloClass)

	RegisterClass (@wndclass)

	'' Register the Rect child window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @RectWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = sizeof (HANDLE)
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast (HBRUSH, GetStockObject (WHITE_BRUSH))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szRectClass)

	RegisterClass (@wndclass)

	'' Obtain handles to three possible menus & submenus

	hMenuInit  = LoadMenu (hInstance, "MdiMenuInit")
	hMenuHello = LoadMenu (hInstance, "MdiMenuHello")
	hMenuRect  = LoadMenu (hInstance, "MdiMenuRect")

	hMenuInitWindow  = GetSubMenu (hMenuInit,   INIT_MENU_POS)
	hMenuHelloWindow = GetSubMenu (hMenuHello, HELLO_MENU_POS)
	hMenuRectWindow  = GetSubMenu (hMenuRect,   RECT_MENU_POS)

	'' Load accelerator table

	hAccel = LoadAccelerators (hInstance, szAppName)

	'' Create the frame window

	hwndFrame = CreateWindow (szFrameClass, "MDI Demonstration", _
		WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN, _
		CW_USEDEFAULT, CW_USEDEFAULT, _
		CW_USEDEFAULT, CW_USEDEFAULT, _
		NULL, hMenuInit, hInstance, NULL)
	hwndClient = GetWindow (hwndFrame, GW_CHILD)

	ShowWindow (hwndFrame, iCmdShow)
	UpdateWindow (hwndFrame)

	'' Enter the modified message loop

	while (GetMessage (@msg, NULL, 0, 0))
		if (TranslateMDISysAccel (hwndClient, @msg) = 0) and  _
				(TranslateAccelerator (hwndFrame, hAccel, @msg) = 0) then
			TranslateMessage (@msg)
			DispatchMessage (@msg)
		end if
	wend
	'' Clean up by deleting unattached menus

	DestroyMenu (hMenuHello)
	DestroyMenu (hMenuRect)

	return msg.wParam
end function


function WndProc (byval hwnd as HWND, byval message as UINT, _
		byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as HWND hwndClient
	dim as CLIENTCREATESTRUCT clientcreate
	dim as HWND hwndChild
	dim as MDICREATESTRUCT mdicreate

	select case message
	case WM_CREATE           '' Create the client window

		clientcreate.hWindowMenu  = hMenuInitWindow
		clientcreate.idFirstChild = IDM_FIRSTCHILD

            Dim as HMENU Menu = CreateMenu
            Dim as HMENU subWindows = CreatePopupMenu 'subMenu
            
            'Menu = CreateMenu
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_CASCADE,"Cascade")
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_TILE,"Tile")
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_ARRANGE,"Arrange")
            AppendMenu(subWindows,MF_STRING,IDM_FILE_EXIT,"Exit")
            
            AppendMenu(Menu,MF_POPUP,Cint(subWindows),"Windows")
            
            DrawMenuBar(hwnd)
            SetMenu(hwnd,Menu)
            
            Dim as HMENU hMenuWindow = CreatePopUpMenu
            
            AppendMenu(hMenuWindow,MF_STRING,IDM_FILE_NEWHELLO,"NewHello")
            AppendMenu(hMenuWindow,MF_STRING,IDM_FILE_NEWRECT,"NewRectangle")
            AppendMenu(hMenuWindow, MF_SEPARATOR, 0, "") 'hSubMenu 
            
            AppendMenu(Menu,MF_POPUP,CInt(hMenuWindow),"File")

			SetMenu(hwnd, Menu) 
			DrawMenuBar(hwnd) 
			
		   hwndClient = CreateWindow ("MDICLIENT", NULL, _
			WS_CHILD or WS_CLIPCHILDREN or WS_VISIBLE, _
			0, 0, 0, 0, hwnd, cast(HMENU, 1), hInst, _
			cast (PSTR, @clientcreate))
		return 0

	case WM_COMMAND
		select case (LOWORD (wParam))
		case IDM_FILE_NEWHELLO       '' Create a Hello child window

			mdicreate.szClass = strptr(szHelloClass)
			mdicreate.szTitle = @"Hello"
			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 = cast(HWND, SendMessage (hwndClient, _
				WM_MDICREATE, 0, _
				cast(LPARAM,@mdicreate)))
			return 0

		case IDM_FILE_NEWRECT        '' Create a Rect child window

			mdicreate.szClass = strptr(szRectClass)
			mdicreate.szTitle = @"Rectangles"
			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 = cast(HWND, SendMessage (hwndClient, _
				WM_MDICREATE, 0, _
				cast(LPARAM, @mdicreate)))
			return 0

		case IDM_FILE_CLOSE          '' Close the active window

			hwndChild = cast(HWND, SendMessage (hwndClient, _
				WM_MDIGETACTIVE, 0, 0))

			if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0) <> 0) then _
				SendMessage (hwndClient, WM_MDIDESTROY, _
				cast(WPARAM, hwndChild), 0)
			return 0
		case IDM_APP_EXIT            '' Exit the program

			SendMessage (hwnd, WM_CLOSE, 0, 0)
			return 0

			'' messages for arranging windows

		case IDM_WINDOW_TILE
			SendMessage (hwndClient, WM_MDITILE, 0, 0)
			return 0

		case IDM_WINDOW_CASCADE
			SendMessage (hwndClient, WM_MDICASCADE, 0, 0)
			return 0

		case IDM_WINDOW_ARRANGE
			SendMessage (hwndClient, WM_MDIICONARRANGE, 0, 0)
			return 0

		case IDM_WINDOW_CLOSEALL     '' Attempt to close all children
			EnumChildWindows (hwndClient, @CloseEnumProc, 0)
			return 0

		case else             '' Pass to active child...

			hwndChild = cast(HWND, SendMessage (hwndClient, _
				WM_MDIGETACTIVE, 0, 0))
			if (IsWindow (hwndChild)) then
				SendMessage (hwndChild, WM_COMMAND, wParam, lParam)
			end if
		end select

	case WM_QUERYENDSESSION, WM_CLOSE                      '' Attempt to close all children

		SendMessage (hwnd, WM_COMMAND, IDM_WINDOW_CLOSEALL, 0)

		if (NULL <> GetWindow (hwndClient, GW_CHILD)) then return 0

	case WM_DESTROY
		PostQuitMessage (0)
		return 0
	end select

	'' Pass unprocessed messages to DefFrameProc (not DefWindowProc)
	return DefFrameProc (hwnd, hwndClient, message, wParam, lParam)
end function

' main loop
End WinMain( GetModuleHandle( NULL ), NULL, Command, SW_NORMAL )

function  HelloWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as COLORREF clrTextArray(0 to 4) => _
          { rgb (0, 0, 0), _
            rgb (0, 0, 255), _
            rgb (0, 255, 0), _
            rgb (255, 0, 0), _
            rgb (255, 255, 255) }

	static as HWND hwndClient, hwndFrame
	dim as HDC hdc
	dim as HMENU hMenu
	dim as PHELLODATA pHelloData
	dim as PAINTSTRUCT ps
	dim as RECT rect

	select case (message)
	case WM_CREATE:
		'' Allocate memory for window private data

		pHelloData = cast(PHELLODATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, sizeof (HELLODATA)))
		pHelloData->iColor  = IDM_COLOR_BLACK
		pHelloData->clrText = rgb (0, 0, 0)
		SetWindowLong (hwnd, 0, cast(long, pHelloData))

		'' Save some window handles

		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		return 0

	case WM_COMMAND
		select case (LOWORD (wParam))
		case IDM_COLOR_BLACK, IDM_COLOR_RED, IDM_COLOR_GREEN, IDM_COLOR_BLUE, IDM_COLOR_WHITE
			'' Change the text color

			pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))

			hMenu = GetMenu (hwndFrame)

			CheckMenuItem (hMenu, pHelloData->iColor, MF_UNCHECKED)
			pHelloData->iColor = wParam
			CheckMenuItem (hMenu, pHelloData->iColor, MF_CHECKED)

			pHelloData->clrText = clrTextArray(wParam - IDM_COLOR_BLACK)

			InvalidateRect (hwnd, NULL, FALSE)
		end select
		return 0

	case WM_PAINT
		'' Paint the window

		hdc = BeginPaint (hwnd, @ps)

		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		SetTextColor (hdc, pHelloData->clrText)

		GetClientRect (hwnd, @rect)

		DrawText (hdc, "Hello, World!", -1, @rect, _
			DT_SINGLELINE or DT_CENTER or DT_VCENTER)

		EndPaint (hwnd, @ps)
		return 0

	case WM_MDIACTIVATE
		'' Set the Hello menu if gaining focus

		if (lParam = cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, _
				cast(WPARAM, hMenuHello), cast(LPARAM, hMenuHelloWindow))
		end if
		'' Check or uncheck menu item

		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		CheckMenuItem (hMenuHello, pHelloData->iColor, _
			(iif(lParam = cast(LPARAM, hwnd), MF_CHECKED, MF_UNCHECKED)))

		'' Set the Init menu if losing focus

		if (lParam <> cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuInit), _
				cast(LPARAM, hMenuInitWindow))
		end if
		DrawMenuBar (hwndFrame)
		return 0

	case WM_QUERYENDSESSION, WM_CLOSE
		if (IDOK <> MessageBox (hwnd, "OK to close window?", _
				"Hello", _
				MB_ICONQUESTION or MB_OKCANCEL)) then return 0

		''else process by DefMDIChildProc

	case WM_DESTROY
		pHelloData = cast(PHELLODATA, GetWindowLong (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pHelloData)
		return 0
	end select
	'' Pass unprocessed message to DefMDIChildProc

	return DefMDIChildProc (hwnd, message, wParam, lParam)
end function

function CloseEnumProc (byval hwnd as HWND, byval lParam as LPARAM) as BOOL

	if (GetWindow (hwnd, GW_OWNER) <> 0) then         '' Check for icon title
		return TRUE
	end if
	SendMessage (GetParent (hwnd), WM_MDIRESTORE, cast(WPARAM, hwnd), 0)

	if (SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0) = 0) then return TRUE

	SendMessage (GetParent (hwnd), WM_MDIDESTROY, cast(WPARAM, hwnd), 0)
	return TRUE
end function

function RectWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as HWND hwndClient, hwndFrame
	dim as HBRUSH      hBrush
	dim as HDC         hdc
	dim as PRECTDATA   pRectData
	dim as PAINTSTRUCT ps
	dim as integer         xLeft, xRight, yTop, yBottom
	dim as short       nRed, nGreen, nBlue

	select case message
	case WM_CREATE
		'' Allocate memory for window private data

		pRectData = cast(PRECTDATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, sizeof (RECTDATA)))

		SetWindowLong (hwnd, 0, cast(long, pRectData))

		'' Start the timer going

		SetTimer (hwnd, 1, 250, NULL)

		'' Save some window handles
		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		return 0

	case WM_SIZE             '' If not minimized, save the window size

		if (wParam <> SIZE_MINIMIZED) then
			pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))

			pRectData->cxClient = LOWORD (lParam)
			pRectData->cyClient = hiword (lParam)
		end if

		'' WM_SIZE must be processed by DefMDIChildProc (no return 0)

	case WM_TIMER            '' Display a random rectangle

		pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))
		xLeft   = rand () mod pRectData->cxClient
		xRight  = rand () mod pRectData->cxClient
		yTop    = rand () mod pRectData->cyClient
		yBottom = rand () mod pRectData->cyClient
		nRed    = rand () and 255
		nGreen  = rand () and 255
		nBlue   = rand () and 255

		hdc = GetDC (hwnd)
		hBrush = CreateSolidBrush (rgb (nRed, nGreen, nBlue))
		SelectObject (hdc, hBrush)

		Rectangle (hdc, min (xLeft, xRight), min (yTop, yBottom), _
			max (xLeft, xRight), max (yTop, yBottom))

		ReleaseDC (hwnd, hdc)
		DeleteObject (hBrush)
		return 0

	case WM_PAINT            '' Clear the window

		InvalidateRect (hwnd, NULL, TRUE)
		hdc = BeginPaint (hwnd, @ps)
		EndPaint (hwnd, @ps)
		return 0

	case WM_MDIACTIVATE      '' Set the appropriate menu
		if (lParam = cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuRect), _
				cast(LPARAM, hMenuRectWindow))
		else
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuInit), _
				cast(LPARAM, hMenuInitWindow))
		end if
		DrawMenuBar (hwndFrame)
		return 0

	case WM_DESTROY
		pRectData = cast(PRECTDATA, GetWindowLong (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pRectData)
		KillTimer (hwnd, 1)
		return 0
	end select

	'' Pass unprocessed message to DefMDIChildProc
	return DefMDIChildProc (hwnd, message, wParam, lParam)
end function

' ends
That was much Work but I am Glad that this mdi example is running now.. I wanted to Break the wall lol

PS: a Link what mdi Interface iS good for:
https://learn.microsoft.com/en-us/windo ... -interface
Last edited by Löwenherz on Oct 31, 2024 9:56, edited 2 times in total.
SARG
Posts: 1888
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Mdi example help

Post by SARG »

Hi Löwenherz,

Nice job. :D

However there is a small error. Selecting exit option doesn't work because the identifier is not the right one.
This line

Code: Select all

AppendMenu(subWindows,MF_STRING,IDM_FILE_EXIT,"Exit")
must be replaced by

Code: Select all

AppendMenu(subWindows,MF_STRING,IDM_APP_EXIT,"Exit")

To be compatible 32/64bit :
- change all GetWindowLong and SetWindowLong by GetWindowLongptr and SetWindowLongptr
- and also replace long by integer in the cast for SetWindowLongptr

Code: Select all

SetWindowLongptr (hwnd, 0, cast(integer, pHelloData))
SetWindowLongptr (hwnd, 0, cast(integer, pRectData))
Löwenherz
Posts: 279
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Mdi example help

Post by Löwenherz »

Thanks for your little corrections Sarg. I didnt Work much with 64bit freebasic but its good oi See how thats working.
The mdi example is able and "easy" to expand with a tab Control and with an included Editor (edit Control scintilla/scilexer for example ) so its become a start Basis for an IDE Editor.. I am Not Sure but winfbe editor of Paul Works at a formerly starting Point in a similar way

Nice Weekend so far a bientot loewenherz
srvaldez
Posts: 3650
Joined: Sep 25, 2005 21:54

Re: Mdi example help

Post by srvaldez »

hello Löwenherz
you need to change all SetWindowLong to SetWindowLongPtr and all SetWindowLongPtr (hwnd, 0, cast(Long to SetWindowLongPtr (hwnd, 0, cast(Integer
then it will compile and run in both 32 and 64 bit, but the rectangles are all black, there's no variation in colors
srvaldez
Posts: 3650
Joined: Sep 25, 2005 21:54

Re: Mdi example help

Post by srvaldez »

here the code with the corrections a mentioned and also some changes to the RectWndProc function, now it draws colored rectangles

Code: Select all

' mdi example, update part two, freebasic, loewenherz
' 30-10-2024, GO :-)
'
#Include "windows.bi"
'#include once "crt.bi"

Dim Shared As HINSTANCE hInst 

Declare Function WndProc(hDlg As hwnd,Msg As uint,wparam As wparam,lparam As lparam) As LRESULT  
Declare Function CloseEnumProc (Byval hwnd As HWND, Byval lParam As LPARAM) As BOOL
Declare Function RectWndProc (Byval hwnd As HWND, Byval message As UINT, _
    Byval wParam As WPARAM, Byval lParam As LPARAM) As LRESULT
Declare Function  HelloWndProc (Byval hwnd As HWND, Byval message As UINT, _
    Byval wParam As WPARAM, Byval lParam As LPARAM) As LRESULT

Dim Shared As HWND hWndMDIClient 

'#define IDM_FILE_NEWHELLO 4001
#Define IDM_FILE_NEWHELLO    40001  
#Define IDM_FILE_NEWRECT     40002
#Define IDM_APP_EXIT         40003
#Define IDM_FILE_CLOSE       40004
#Define IDM_COLOR_BLACK      40005
#Define IDM_COLOR_RED        40006
#Define IDM_COLOR_GREEN      40007
#Define IDM_COLOR_BLUE       40008
#Define IDM_COLOR_WHITE      40009
#Define IDM_WINDOW_CASCADE   40010
#Define IDM_WINDOW_TILE      40011
#Define IDM_WINDOW_ARRANGE   40012
#Define IDM_WINDOW_CLOSEALL  40013

#Define INIT_MENU_POS    0
#Define HELLO_MENU_POS   2
#Define RECT_MENU_POS    1

#Define IDM_FIRSTCHILD   50000
#Define IDM_FILE_EXIT    50001

Type HELLODATA
	As UINT     iColor
	As COLORREF clrText
End Type
Type PHELLODATA As HELLODATA Ptr

'' structure for storing data unique to each Rect child window

Type RECTDATA
	As Short cxClient
	As Short cyClient
End Type
Type PRECTDATA As RECTDATA Ptr


'' global variables
Dim Shared As String szAppName
szAppName    = "MDIDemo"
Dim Shared As String szFrameClass
szFrameClass = "MdiFrame"
Dim Shared As String szHelloClass
szHelloClass = "MdiHelloChild"
Dim Shared As String szRectClass
szRectClass  = "MdiRectChild"

'dim shared as HINSTANCE hInst
Dim Shared As HMENU hMenuInit, hMenuHello, hMenuRect
Dim Shared As HMENU hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow


Function WinMain (Byval hInstance As HINSTANCE, _
		Byval hPrevInstance As HINSTANCE, _
		Byval szCmdLine As String, _
		Byval iCmdShow As Integer) As Integer

	Dim As HACCEL   hAccel
	Dim As HWND     hwndFrame, hwndClient
	Dim As MSG      msg
	Dim As WNDCLASS wndclass

	hInst = hInstance

	'' Register the frame window class

	wndclass.style         = CS_HREDRAW Or CS_VREDRAW
	wndclass.lpfnWndProc   = @WndProc 
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = 0
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = Cast(HBRUSH, (COLOR_APPWORKSPACE + 1))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = Strptr(szFrameClass)

	If RegisterClass (@wndclass) = 0 Then
		MessageBox (NULL, "This program requires Windows!", _
			szAppName, MB_ICONERROR)
		Return 0
	End If

	'' Register the Hello child window class

	wndclass.style         = CS_HREDRAW Or CS_VREDRAW
	wndclass.lpfnWndProc   = @HelloWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = Sizeof (HANDLE)
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = Cast(HBRUSH, GetStockObject (WHITE_BRUSH))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = Strptr(szHelloClass)

	RegisterClass (@wndclass)

	'' Register the Rect child window class

	wndclass.style         = CS_HREDRAW Or CS_VREDRAW
	wndclass.lpfnWndProc   = @RectWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = Sizeof (HANDLE)
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = Cast (HBRUSH, GetStockObject (WHITE_BRUSH))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = Strptr(szRectClass)

	RegisterClass (@wndclass)

	'' Obtain handles to three possible menus & submenus

	hMenuInit  = LoadMenu (hInstance, "MdiMenuInit")
	hMenuHello = LoadMenu (hInstance, "MdiMenuHello")
	hMenuRect  = LoadMenu (hInstance, "MdiMenuRect")

	hMenuInitWindow  = GetSubMenu (hMenuInit,   INIT_MENU_POS)
	hMenuHelloWindow = GetSubMenu (hMenuHello, HELLO_MENU_POS)
	hMenuRectWindow  = GetSubMenu (hMenuRect,   RECT_MENU_POS)

	'' Load accelerator table

	hAccel = LoadAccelerators (hInstance, szAppName)

	'' Create the frame window

	hwndFrame = CreateWindow (szFrameClass, "MDI Demonstration", _
		WS_OVERLAPPEDWINDOW Or WS_CLIPCHILDREN, _
		CW_USEDEFAULT, CW_USEDEFAULT, _
		CW_USEDEFAULT, CW_USEDEFAULT, _
		NULL, hMenuInit, hInstance, NULL)
	hwndClient = GetWindow (hwndFrame, GW_CHILD)

	ShowWindow (hwndFrame, iCmdShow)
	UpdateWindow (hwndFrame)

	'' Enter the modified message loop

	While (GetMessage (@msg, NULL, 0, 0))
		If (TranslateMDISysAccel (hwndClient, @msg) = 0) And  _
				(TranslateAccelerator (hwndFrame, hAccel, @msg) = 0) Then
			TranslateMessage (@msg)
			DispatchMessage (@msg)
		End If
	Wend
	'' Clean up by deleting unattached menus

	DestroyMenu (hMenuHello)
	DestroyMenu (hMenuRect)

	Return msg.wParam
End Function


Function WndProc (Byval hwnd As HWND, Byval message As UINT, _
		Byval wParam As WPARAM, Byval lParam As LPARAM) As LRESULT

	Static As HWND hwndClient
	Dim As CLIENTCREATESTRUCT clientcreate
	Dim As HWND hwndChild
	Dim As MDICREATESTRUCT mdicreate

	Select Case message
	Case WM_CREATE           '' Create the client window

		clientcreate.hWindowMenu  = hMenuInitWindow
		clientcreate.idFirstChild = IDM_FIRSTCHILD

            Dim As HMENU Menu = CreateMenu
            Dim As HMENU subWindows = CreatePopupMenu 'subMenu
            
            'Menu = CreateMenu
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_CASCADE,"Cascade")
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_TILE,"Tile")
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_ARRANGE,"Arrange")
            AppendMenu(subWindows,MF_STRING,IDM_FILE_EXIT,"Exit")
            
            AppendMenu(Menu,MF_POPUP,Cint(subWindows),"Windows")
            
            DrawMenuBar(hwnd)
            SetMenu(hwnd,Menu)
            
            Dim As HMENU hMenuWindow = CreatePopUpMenu
            
            AppendMenu(hMenuWindow,MF_STRING,IDM_FILE_NEWHELLO,"NewHello")
            AppendMenu(hMenuWindow,MF_STRING,IDM_FILE_NEWRECT,"NewRectangle")
            AppendMenu(hMenuWindow, MF_SEPARATOR, 0, "") 'hSubMenu 
            
            AppendMenu(Menu,MF_POPUP,Cint(hMenuWindow),"File")

			SetMenu(hwnd, Menu) 
			DrawMenuBar(hwnd) 
			
		   hwndClient = CreateWindow ("MDICLIENT", NULL, _
			WS_CHILD Or WS_CLIPCHILDREN Or WS_VISIBLE, _
			0, 0, 0, 0, hwnd, Cast(HMENU, 1), hInst, _
			Cast (PSTR, @clientcreate))
		Return 0

	Case WM_COMMAND
		Select Case (Loword (wParam))
		Case IDM_FILE_NEWHELLO       '' Create a Hello child window

			mdicreate.szClass = Strptr(szHelloClass)
			mdicreate.szTitle = @"Hello"
			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 = Cast(HWND, SendMessage (hwndClient, _
				WM_MDICREATE, 0, _
				Cast(LPARAM,@mdicreate)))
			Return 0

		Case IDM_FILE_NEWRECT        '' Create a Rect child window

			mdicreate.szClass = Strptr(szRectClass)
			mdicreate.szTitle = @"Rectangles"
			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 = Cast(HWND, SendMessage (hwndClient, _
				WM_MDICREATE, 0, _
				Cast(LPARAM, @mdicreate)))
			Return 0

		Case IDM_FILE_CLOSE          '' Close the active window

			hwndChild = Cast(HWND, SendMessage (hwndClient, _
				WM_MDIGETACTIVE, 0, 0))

			If (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0) <> 0) Then _
				SendMessage (hwndClient, WM_MDIDESTROY, _
				Cast(WPARAM, hwndChild), 0)
			Return 0
		Case IDM_APP_EXIT            '' Exit the program

			SendMessage (hwnd, WM_CLOSE, 0, 0)
			Return 0

			'' messages for arranging windows

		Case IDM_WINDOW_TILE
			SendMessage (hwndClient, WM_MDITILE, 0, 0)
			Return 0

		Case IDM_WINDOW_CASCADE
			SendMessage (hwndClient, WM_MDICASCADE, 0, 0)
			Return 0

		Case IDM_WINDOW_ARRANGE
			SendMessage (hwndClient, WM_MDIICONARRANGE, 0, 0)
			Return 0

		Case IDM_WINDOW_CLOSEALL     '' Attempt to close all children
			EnumChildWindows (hwndClient, @CloseEnumProc, 0)
			Return 0

		Case Else             '' Pass to active child...

			hwndChild = Cast(HWND, SendMessage (hwndClient, _
				WM_MDIGETACTIVE, 0, 0))
			If (IsWindow (hwndChild)) Then
				SendMessage (hwndChild, WM_COMMAND, wParam, lParam)
			End If
		End Select

	Case WM_QUERYENDSESSION, WM_CLOSE                      '' Attempt to close all children

		SendMessage (hwnd, WM_COMMAND, IDM_WINDOW_CLOSEALL, 0)

		If (NULL <> GetWindow (hwndClient, GW_CHILD)) Then Return 0

	Case WM_DESTROY
		PostQuitMessage (0)
		Return 0
	End Select

	'' Pass unprocessed messages to DefFrameProc (not DefWindowProc)
	Return DefFrameProc (hwnd, hwndClient, message, wParam, lParam)
End Function

' main loop
End WinMain( GetModuleHandle( NULL ), NULL, Command, SW_NORMAL )

Function  HelloWndProc (Byval hwnd As HWND, Byval message As UINT, _
    Byval wParam As WPARAM, Byval lParam As LPARAM) As LRESULT

	Static As COLORREF clrTextArray(0 To 4) => _
          { Rgb (0, 0, 0), _
            Rgb (0, 0, 255), _
            Rgb (0, 255, 0), _
            Rgb (255, 0, 0), _
            Rgb (255, 255, 255) }

	Static As HWND hwndClient, hwndFrame
	Dim As HDC hdc
	Dim As HMENU hMenu
	Dim As PHELLODATA pHelloData
	Dim As PAINTSTRUCT ps
	Dim As RECT rect

	Select Case (message)
	Case WM_CREATE:
		'' Allocate memory for window private data

		pHelloData = Cast(PHELLODATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, Sizeof (HELLODATA)))
		pHelloData->iColor  = IDM_COLOR_BLACK
		pHelloData->clrText = Rgb (0, 0, 0)
		SetWindowLongPtr (hwnd, 0, Cast(Integer, pHelloData))

		'' Save some window handles

		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		Return 0

	Case WM_COMMAND
		Select Case (Loword (wParam))
		Case IDM_COLOR_BLACK, IDM_COLOR_RED, IDM_COLOR_GREEN, IDM_COLOR_BLUE, IDM_COLOR_WHITE
			'' Change the text color

			pHelloData = Cast(PHELLODATA, GetWindowLongPtr (hwnd, 0))

			hMenu = GetMenu (hwndFrame)

			CheckMenuItem (hMenu, pHelloData->iColor, MF_UNCHECKED)
			pHelloData->iColor = wParam
			CheckMenuItem (hMenu, pHelloData->iColor, MF_CHECKED)

			pHelloData->clrText = clrTextArray(wParam - IDM_COLOR_BLACK)

			InvalidateRect (hwnd, NULL, FALSE)
		End Select
		Return 0

	Case WM_PAINT
		'' Paint the window

		hdc = BeginPaint (hwnd, @ps)

		pHelloData = Cast(PHELLODATA, GetWindowLongPtr (hwnd, 0))
		SetTextColor (hdc, pHelloData->clrText)

		GetClientRect (hwnd, @rect)

		DrawText (hdc, "Hello, World!", -1, @rect, _
			DT_SINGLELINE Or DT_CENTER Or DT_VCENTER)

		EndPaint (hwnd, @ps)
		Return 0

	Case WM_MDIACTIVATE
		'' Set the Hello menu if gaining focus

		If (lParam = Cast(LPARAM, hwnd)) Then
			SendMessage (hwndClient, WM_MDISETMENU, _
				Cast(WPARAM, hMenuHello), Cast(LPARAM, hMenuHelloWindow))
		End If
		'' Check or uncheck menu item

		pHelloData = Cast(PHELLODATA, GetWindowLongPtr (hwnd, 0))
		CheckMenuItem (hMenuHello, pHelloData->iColor, _
			(Iif(lParam = Cast(LPARAM, hwnd), MF_CHECKED, MF_UNCHECKED)))

		'' Set the Init menu if losing focus

		If (lParam <> Cast(LPARAM, hwnd)) Then
			SendMessage (hwndClient, WM_MDISETMENU, Cast(WPARAM, hMenuInit), _
				Cast(LPARAM, hMenuInitWindow))
		End If
		DrawMenuBar (hwndFrame)
		Return 0

	Case WM_QUERYENDSESSION, WM_CLOSE
		If (IDOK <> MessageBox (hwnd, "OK to close window?", _
				"Hello", _
				MB_ICONQUESTION Or MB_OKCANCEL)) Then Return 0

		''else process by DefMDIChildProc

	Case WM_DESTROY
		pHelloData = Cast(PHELLODATA, GetWindowLongPtr (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pHelloData)
		Return 0
	End Select
	'' Pass unprocessed message to DefMDIChildProc

	Return DefMDIChildProc (hwnd, message, wParam, lParam)
End Function

Function CloseEnumProc (Byval hwnd As HWND, Byval lParam As LPARAM) As BOOL

	If (GetWindow (hwnd, GW_OWNER) <> 0) Then         '' Check for icon title
		Return TRUE
	End If
	SendMessage (GetParent (hwnd), WM_MDIRESTORE, Cast(WPARAM, hwnd), 0)

	If (SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0) = 0) Then Return TRUE

	SendMessage (GetParent (hwnd), WM_MDIDESTROY, Cast(WPARAM, hwnd), 0)
	Return TRUE
End Function

Function RectWndProc (Byval hwnd As HWND, Byval message As UINT, _
    Byval wParam As WPARAM, Byval lParam As LPARAM) As LRESULT

	Static As HWND hwndClient, hwndFrame
	Dim As HBRUSH      hBrush
	Dim As HDC         hdc
	Dim As PRECTDATA   pRectData
	Dim As PAINTSTRUCT ps
	Dim As Integer         xLeft, xRight, yTop, yBottom
	Dim As Short       nAlpha, nRed, nGreen, nBlue

	Select Case message
	Case WM_CREATE
		'' Allocate memory for window private data

		pRectData = Cast(PRECTDATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, Sizeof (RECTDATA)))

		SetWindowLongPtr (hwnd, 0, Cast(Integer, pRectData))

		'' Start the timer going

		SetTimer (hwnd, 1, 250, NULL)

		'' Save some window handles
		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		Return 0

	Case WM_SIZE             '' If not minimized, save the window size

		If (wParam <> SIZE_MINIMIZED) Then
			pRectData = Cast(PRECTDATA, GetWindowLongPtr (hwnd, 0))

			pRectData->cxClient = Loword (lParam)
			pRectData->cyClient = Hiword (lParam)
		End If

		'' WM_SIZE must be processed by DefMDIChildProc (no return 0)

	Case WM_TIMER            '' Display a random rectangle

		pRectData = Cast(PRECTDATA, GetWindowLongPtr (hwnd, 0))
		xLeft   = rand () Mod pRectData->cxClient
		xRight  = rand () Mod pRectData->cxClient
		yTop    = rand () Mod pRectData->cyClient
		yBottom = rand () Mod pRectData->cyClient
		nRed    = Rnd *255 'and 256
		nGreen  = Rnd *255 'and 256
		nBlue   = Rnd *255 'and 256
		nBlue   = Rnd *255 

		hdc = GetDC (hwnd)
		Dim As COLORREF colour = Rgba(nAlpha, nRed, nGreen, nBlue)
		hBrush = CreateSolidBrush (colour)
		SelectObject (hdc, hBrush)

		Rectangle (hdc, min (xLeft, xRight), min (yTop, yBottom), _
			max (xLeft, xRight), max (yTop, yBottom))

		ReleaseDC (hwnd, hdc)
		DeleteObject (hBrush)
		Return 0

	Case WM_PAINT            '' Clear the window

		InvalidateRect (hwnd, NULL, TRUE)
		hdc = BeginPaint (hwnd, @ps)
		EndPaint (hwnd, @ps)
		Return 0

	Case WM_MDIACTIVATE      '' Set the appropriate menu
		If (lParam = Cast(LPARAM, hwnd)) Then
			SendMessage (hwndClient, WM_MDISETMENU, Cast(WPARAM, hMenuRect), _
				Cast(LPARAM, hMenuRectWindow))
		Else
			SendMessage (hwndClient, WM_MDISETMENU, Cast(WPARAM, hMenuInit), _
				Cast(LPARAM, hMenuInitWindow))
		End If
		DrawMenuBar (hwndFrame)
		Return 0

	Case WM_DESTROY
		pRectData = Cast(PRECTDATA, GetWindowLongPtr (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pRectData)
		KillTimer (hwnd, 1)
		Return 0
	End Select

	'' Pass unprocessed message to DefMDIChildProc
	Return DefMDIChildProc (hwnd, message, wParam, lParam)
End Function

' ends
[/code[
SARG
Posts: 1888
Joined: May 27, 2005 7:15
Location: FRANCE

Re: Mdi example help

Post by SARG »

@srvaldez
Did you see and read my post above about Get/SetWindowLong and long/integer ? :lol:
srvaldez
Posts: 3650
Joined: Sep 25, 2005 21:54

Re: Mdi example help

Post by srvaldez »

sorry SARG, I saw it but when I tried Löwenherz last entry I thought that he would have made the corrections that you mentioned, but when I tried to compile in 64-bit I encountered errors
Löwenherz
Posts: 279
Joined: Aug 27, 2008 6:26
Location: Bad Sooden-Allendorf, Germany

Re: Mdi example help

Post by Löwenherz »

New Edit:
Here's my corrected Version with Sarg's advices (and still without colored rectangles of srvaldez expl )

And my new Question is how to submenu my Color Menu below "File" ? If you click "File" NewHello there should BE the new Color Menu to Change the Color of Hello string

Thanks srvaldez for your example you we're too fast.. That or another mdi example with colored hello Text I was still looking for.. on my Notebook ...have at the Moment a little time Problem but will find this example and wanted to expand it too. All Work in progress

Code: Select all

' mdi example, update part three, freebasic, loewenherz
' 30-10-2024, GO :-) / 01-11-2024 corrections made for this example, thanks sarg
' running example for 32 bit and 64 bit
'
#Include "windows.bi"
'#include once "crt.bi"

Dim Shared As HINSTANCE hInst 

Declare Function WndProc(hDlg as hwnd,Msg as uint,wparam as wparam,lparam as lparam) as LRESULT  
Declare function CloseEnumProc (byval hwnd as HWND, byval lParam as LPARAM) as BOOL
Declare function RectWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT
declare function  HelloWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

Dim Shared As HWND hWndMDIClient 

'#define IDM_FILE_NEWHELLO 4001
#Define IDM_FILE_NEWHELLO    40001  
#Define IDM_FILE_NEWRECT     40002
#Define IDM_APP_EXIT         40003
#Define IDM_FILE_CLOSE       40004
#Define IDM_COLOR_BLACK      40005
#Define IDM_COLOR_RED        40006
#Define IDM_COLOR_GREEN      40007
#Define IDM_COLOR_BLUE       40008
#Define IDM_COLOR_WHITE      40009
#Define IDM_WINDOW_CASCADE   40010
#Define IDM_WINDOW_TILE      40011
#Define IDM_WINDOW_ARRANGE   40012
#Define IDM_WINDOW_CLOSEALL  40013

#Define INIT_MENU_POS    0
#Define HELLO_MENU_POS   2
#Define RECT_MENU_POS    1

#Define IDM_FIRSTCHILD   50000
#Define IDM_FILE_EXIT    50001

type HELLODATA
	as UINT     iColor
	as COLORREF clrText
end type
type PHELLODATA as HELLODATA ptr

'' structure for storing data unique to each Rect child window

type RECTDATA
	as short cxClient
	as short cyClient
end type
type PRECTDATA as RECTDATA ptr


'' global variables
dim shared as string szAppName
szAppName    = "MDIDemo"
dim shared as string szFrameClass
szFrameClass = "MdiFrame"
dim shared as string szHelloClass
szHelloClass = "MdiHelloChild"
dim shared as string szRectClass
szRectClass  = "MdiRectChild"

'dim shared as HINSTANCE hInst
dim shared as HMENU hMenuInit, hMenuHello, hMenuRect
dim shared as HMENU hMenuInitWindow, hMenuHelloWindow, hMenuRectWindow


function WinMain (byval hInstance as HINSTANCE, _
		byval hPrevInstance as HINSTANCE, _
		byval szCmdLine as string, _
		byval iCmdShow as integer) as integer

	dim as HACCEL   hAccel
	dim as HWND     hwndFrame, hwndClient
	dim as MSG      msg
	dim as WNDCLASS wndclass

	hInst = hInstance

	'' Register the frame window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @WndProc 
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = 0
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast(HBRUSH, (COLOR_APPWORKSPACE + 1))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szFrameClass)

	if RegisterClass (@wndclass) = 0 then
		MessageBox (NULL, "This program requires Windows!", _
			szAppName, MB_ICONERROR)
		return 0
	end if

	'' Register the Hello child window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @HelloWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = sizeof (HANDLE)
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast(HBRUSH, GetStockObject (WHITE_BRUSH))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szHelloClass)

	RegisterClass (@wndclass)

	'' Register the Rect child window class

	wndclass.style         = CS_HREDRAW or CS_VREDRAW
	wndclass.lpfnWndProc   = @RectWndProc
	wndclass.cbClsExtra    = 0
	wndclass.cbWndExtra    = sizeof (HANDLE)
	wndclass.hInstance     = hInstance
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION)
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW)
	wndclass.hbrBackground = cast (HBRUSH, GetStockObject (WHITE_BRUSH))
	wndclass.lpszMenuName  = NULL
	wndclass.lpszClassName = strptr(szRectClass)

	RegisterClass (@wndclass)

	'' Obtain handles to three possible menus & submenus

	hMenuInit  = LoadMenu (hInstance, "MdiMenuInit")
	hMenuHello = LoadMenu (hInstance, "MdiMenuHello")
	hMenuRect  = LoadMenu (hInstance, "MdiMenuRect")

	hMenuInitWindow  = GetSubMenu (hMenuInit,   INIT_MENU_POS)
	hMenuHelloWindow = GetSubMenu (hMenuHello, HELLO_MENU_POS)
	hMenuRectWindow  = GetSubMenu (hMenuRect,   RECT_MENU_POS)

	'' Load accelerator table

	hAccel = LoadAccelerators (hInstance, szAppName)

	'' Create the frame window

	hwndFrame = CreateWindow (szFrameClass, "MDI Demonstration", _
		WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN, _
		CW_USEDEFAULT, CW_USEDEFAULT, _
		CW_USEDEFAULT, CW_USEDEFAULT, _
		NULL, hMenuInit, hInstance, NULL)
	hwndClient = GetWindow (hwndFrame, GW_CHILD)

	ShowWindow (hwndFrame, iCmdShow)
	UpdateWindow (hwndFrame)

	'' Enter the modified message loop

	while (GetMessage (@msg, NULL, 0, 0))
		if (TranslateMDISysAccel (hwndClient, @msg) = 0) and  _
				(TranslateAccelerator (hwndFrame, hAccel, @msg) = 0) then
			TranslateMessage (@msg)
			DispatchMessage (@msg)
		end if
	wend
	'' Clean up by deleting unattached menus

	DestroyMenu (hMenuHello)
	DestroyMenu (hMenuRect)

	return msg.wParam
end function


function WndProc (byval hwnd as HWND, byval message as UINT, _
		byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as HWND hwndClient
	dim as CLIENTCREATESTRUCT clientcreate
	dim as HWND hwndChild
	dim as MDICREATESTRUCT mdicreate

	select case message
	case WM_CREATE           '' Create the client window

		clientcreate.hWindowMenu  = hMenuInitWindow
		clientcreate.idFirstChild = IDM_FIRSTCHILD

            Dim as HMENU Menu = CreateMenu
            Dim as HMENU subWindows = CreatePopupMenu 'subMenu
            
            'Menu = CreateMenu
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_CASCADE,"Cascade")
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_TILE,"Tile")
            AppendMenu(subWindows,MF_STRING,IDM_WINDOW_ARRANGE,"Arrange")
            AppendMenu(subWindows,MF_STRING,IDM_APP_EXIT,"Exit") 'IDM_FILE_EXIT 
            
            AppendMenu(Menu,MF_POPUP,Cint(subWindows),"Windows")
            
            DrawMenuBar(hwnd)
            SetMenu(hwnd,Menu)
            
            Dim as HMENU hMenuWindow = CreatePopUpMenu
            
            AppendMenu(hMenuWindow,MF_STRING,IDM_FILE_NEWHELLO,"NewHello")
            AppendMenu(hMenuWindow,MF_STRING,IDM_FILE_NEWRECT,"NewRectangle")
            AppendMenu(hMenuWindow, MF_SEPARATOR, 0, "") 'hSubMenu 

            AppendMenu(Menu,MF_POPUP,CInt(hMenuWindow),"File")

            Dim as HMENU hMenuCol = CreatePopUpMenu
            
            AppendMenu(hMenuCol,MF_STRING,IDM_COLOR_BLACK,"Black")
            AppendMenu(hMenuCol,MF_STRING,IDM_COLOR_RED,"Red")
            AppendMenu(hMenuCol, MF_SEPARATOR, 0, "") 'hSubMenu 
            AppendMenu(hMenuCol,MF_STRING,IDM_COLOR_GREEN,"Green")
            AppendMenu(hMenuCol,MF_STRING,IDM_COLOR_BLUE,"Blue")
            AppendMenu(hMenuCol,MF_STRING,IDM_COLOR_WHITE,"White")
                        
            AppendMenu(Menu,MF_POPUP,CInt(hMenuCol),"Color") 'hMenuCol

			SetMenu(hwnd, Menu) 
			DrawMenuBar(hwnd) 
			
		   hwndClient = CreateWindow ("MDICLIENT", NULL, _
			WS_CHILD or WS_CLIPCHILDREN or WS_VISIBLE, _
			0, 0, 0, 0, hwnd, cast(HMENU, 1), hInst, _
			cast (PSTR, @clientcreate))
		return 0

	case WM_COMMAND
		select case (LOWORD (wParam))
		case IDM_FILE_NEWHELLO       '' Create a Hello child window

			mdicreate.szClass = strptr(szHelloClass)
			mdicreate.szTitle = @"Hello"
			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 = cast(HWND, SendMessage (hwndClient, _
				WM_MDICREATE, 0, _
				cast(LPARAM,@mdicreate)))
			return 0

		case IDM_FILE_NEWRECT        '' Create a Rect child window

			mdicreate.szClass = strptr(szRectClass)
			mdicreate.szTitle = @"Rectangles"
			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 = cast(HWND, SendMessage (hwndClient, _
				WM_MDICREATE, 0, _
				cast(LPARAM, @mdicreate)))
			return 0

		case IDM_FILE_CLOSE          '' Close the active window

			hwndChild = cast(HWND, SendMessage (hwndClient, _
				WM_MDIGETACTIVE, 0, 0))

			if (SendMessage (hwndChild, WM_QUERYENDSESSION, 0, 0) <> 0) then _
				SendMessage (hwndClient, WM_MDIDESTROY, _
				cast(WPARAM, hwndChild), 0)
			return 0
		case IDM_APP_EXIT            '' Exit the program

			SendMessage (hwnd, WM_CLOSE, 0, 0)
			return 0

			'' messages for arranging windows

		case IDM_WINDOW_TILE
			SendMessage (hwndClient, WM_MDITILE, 0, 0)
			return 0

		case IDM_WINDOW_CASCADE
			SendMessage (hwndClient, WM_MDICASCADE, 0, 0)
			return 0

		case IDM_WINDOW_ARRANGE
			SendMessage (hwndClient, WM_MDIICONARRANGE, 0, 0)
			return 0

		case IDM_WINDOW_CLOSEALL     '' Attempt to close all children
			EnumChildWindows (hwndClient, @CloseEnumProc, 0)
			return 0

		case else             '' Pass to active child...

			hwndChild = cast(HWND, SendMessage (hwndClient, _
				WM_MDIGETACTIVE, 0, 0))
			if (IsWindow (hwndChild)) then
				SendMessage (hwndChild, WM_COMMAND, wParam, lParam)
			end if
		end select

	case WM_QUERYENDSESSION, WM_CLOSE                      '' Attempt to close all children

		SendMessage (hwnd, WM_COMMAND, IDM_WINDOW_CLOSEALL, 0)

		if (NULL <> GetWindow (hwndClient, GW_CHILD)) then return 0

	case WM_DESTROY
		PostQuitMessage (0)
		return 0
	end select

	'' Pass unprocessed messages to DefFrameProc (not DefWindowProc)
	return DefFrameProc (hwnd, hwndClient, message, wParam, lParam)
end function

' main loop
End WinMain( GetModuleHandle( NULL ), NULL, Command, SW_NORMAL )

function  HelloWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as COLORREF clrTextArray(0 to 4) => _
          { rgb (0, 0, 0), _
            rgb (0, 0, 255), _
            rgb (0, 255, 0), _
            rgb (255, 0, 0), _
            rgb (255, 255, 255) }

	static as HWND hwndClient, hwndFrame
	dim as HDC hdc
	dim as HMENU hMenu
	dim as PHELLODATA pHelloData
	dim as PAINTSTRUCT ps
	dim as RECT rect

	select case (message)
	case WM_CREATE:
		'' Allocate memory for window private data

		pHelloData = cast(PHELLODATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, sizeof (HELLODATA)))
		pHelloData->iColor  = IDM_COLOR_BLACK
		pHelloData->clrText = rgb (0, 0, 0)
		SetWindowLongPtr (hwnd, 0, cast(integer, pHelloData))

		'' Save some window handles

		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		return 0

	case WM_COMMAND
		select case (LOWORD (wParam))
		case IDM_COLOR_BLACK, IDM_COLOR_RED, IDM_COLOR_GREEN, IDM_COLOR_BLUE, IDM_COLOR_WHITE
			'' Change the text color

			pHelloData = cast(PHELLODATA, GetWindowLongPtr (hwnd, 0))

			hMenu = GetMenu (hwndFrame)

			CheckMenuItem (hMenu, pHelloData->iColor, MF_UNCHECKED)
			pHelloData->iColor = wParam
			CheckMenuItem (hMenu, pHelloData->iColor, MF_CHECKED)

			pHelloData->clrText = clrTextArray(wParam - IDM_COLOR_BLACK)

			InvalidateRect (hwnd, NULL, FALSE)
		end select
		return 0

	case WM_PAINT
		'' Paint the window

		hdc = BeginPaint (hwnd, @ps)

		pHelloData = cast(PHELLODATA, GetWindowLongPtr (hwnd, 0))
		SetTextColor (hdc, pHelloData->clrText)

		GetClientRect (hwnd, @rect)

		DrawText (hdc, "Hello, World!", -1, @rect, _
			DT_SINGLELINE or DT_CENTER or DT_VCENTER)

		EndPaint (hwnd, @ps)
		return 0

	case WM_MDIACTIVATE
		'' Set the Hello menu if gaining focus

		if (lParam = cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, _
				cast(WPARAM, hMenuHello), cast(LPARAM, hMenuHelloWindow))
		end if
		'' Check or uncheck menu item

		pHelloData = cast(PHELLODATA, GetWindowLongPtr (hwnd, 0))
		CheckMenuItem (hMenuHello, pHelloData->iColor, _
			(iif(lParam = cast(LPARAM, hwnd), MF_CHECKED, MF_UNCHECKED)))

		'' Set the Init menu if losing focus

		if (lParam <> cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuInit), _
				cast(LPARAM, hMenuInitWindow))
		end if
		DrawMenuBar (hwndFrame)
		return 0

	case WM_QUERYENDSESSION, WM_CLOSE
		if (IDOK <> MessageBox (hwnd, "OK to close window?", _
				"Hello", _
				MB_ICONQUESTION or MB_OKCANCEL)) then return 0

		''else process by DefMDIChildProc

	case WM_DESTROY
		pHelloData = cast(PHELLODATA, GetWindowLongPtr (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pHelloData)
		return 0
	end select
	'' Pass unprocessed message to DefMDIChildProc

	return DefMDIChildProc (hwnd, message, wParam, lParam)
end function

function CloseEnumProc (byval hwnd as HWND, byval lParam as LPARAM) as BOOL

	if (GetWindow (hwnd, GW_OWNER) <> 0) then         '' Check for icon title
		return TRUE
	end if
	SendMessage (GetParent (hwnd), WM_MDIRESTORE, cast(WPARAM, hwnd), 0)

	if (SendMessage (hwnd, WM_QUERYENDSESSION, 0, 0) = 0) then return TRUE

	SendMessage (GetParent (hwnd), WM_MDIDESTROY, cast(WPARAM, hwnd), 0)
	return TRUE
end function

function RectWndProc (byval hwnd as HWND, byval message as UINT, _
    byval wParam as WPARAM, byval lParam as LPARAM) as LRESULT

	static as HWND hwndClient, hwndFrame
	dim as HBRUSH      hBrush
	dim as HDC         hdc
	dim as PRECTDATA   pRectData
	dim as PAINTSTRUCT ps
	dim as integer         xLeft, xRight, yTop, yBottom
	dim as short       nRed, nGreen, nBlue

	select case message
	case WM_CREATE
		'' Allocate memory for window private data

		pRectData = cast(PRECTDATA, HeapAlloc (GetProcessHeap (), _
			HEAP_ZERO_MEMORY, sizeof (RECTDATA)))

		SetWindowLongPtr (hwnd, 0, cast(integer, pRectData))

		'' Start the timer going

		SetTimer (hwnd, 1, 250, NULL)

		'' Save some window handles
		hwndClient = GetParent (hwnd)
		hwndFrame  = GetParent (hwndClient)
		return 0

	case WM_SIZE             '' If not minimized, save the window size

		if (wParam <> SIZE_MINIMIZED) then
			pRectData = cast(PRECTDATA, GetWindowLongPtr (hwnd, 0))

			pRectData->cxClient = LOWORD (lParam)
			pRectData->cyClient = hiword (lParam)
		end if

		'' WM_SIZE must be processed by DefMDIChildProc (no return 0)

	case WM_TIMER            '' Display a random rectangle

		pRectData = cast(PRECTDATA, GetWindowLongPtr (hwnd, 0))
		xLeft   = rand () mod pRectData->cxClient
		xRight  = rand () mod pRectData->cxClient
		yTop    = rand () mod pRectData->cyClient
		yBottom = rand () mod pRectData->cyClient
		nRed    = rand () and 255
		nGreen  = rand () and 255
		nBlue   = rand () and 255

		hdc = GetDC (hwnd)
		hBrush = CreateSolidBrush (rgb (nRed, nGreen, nBlue))
		SelectObject (hdc, hBrush)

		Rectangle (hdc, min (xLeft, xRight), min (yTop, yBottom), _
			max (xLeft, xRight), max (yTop, yBottom))

		ReleaseDC (hwnd, hdc)
		DeleteObject (hBrush)
		return 0

	case WM_PAINT            '' Clear the window

		InvalidateRect (hwnd, NULL, TRUE)
		hdc = BeginPaint (hwnd, @ps)
		EndPaint (hwnd, @ps)
		return 0

	case WM_MDIACTIVATE      '' Set the appropriate menu
		if (lParam = cast(LPARAM, hwnd)) then
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuRect), _
				cast(LPARAM, hMenuRectWindow))
		else
			SendMessage (hwndClient, WM_MDISETMENU, cast(WPARAM, hMenuInit), _
				cast(LPARAM, hMenuInitWindow))
		end if
		DrawMenuBar (hwndFrame)
		return 0

	case WM_DESTROY
		pRectData = cast(PRECTDATA, GetWindowLongPtr (hwnd, 0))
		HeapFree (GetProcessHeap (), 0, pRectData)
		KillTimer (hwnd, 1)
		return 0
	end select

	'' Pass unprocessed message to DefMDIChildProc
	return DefMDIChildProc (hwnd, message, wParam, lParam)
end function

' ends

[
Last edited by Löwenherz on Nov 01, 2024 20:06, edited 3 times in total.
srvaldez
Posts: 3650
Joined: Sep 25, 2005 21:54

Re: Mdi example help

Post by srvaldez »

you missed lines 373, 393, 414, 468, 478, 517
I suggest that try to compile in 64-bit before posting, and the rectangles are all black, see my posted mod above
Post Reply