MDI Example

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by webmatze.

I played around with the Windows API and the result is this little pice of code.

But there are still some bugs. The first Child Window is not painted properly.

Does anybody know what the fault is?

Code: Select all

#RICHEDIT = #WS_CHILD | #WS_VISIBLE |#WS_VSCROLL |#ES_MULTILINE |#ES_AUTOVSCROLL
#WINDOW_PARAMETERS = #PB_Window_SystemMenu

#WindowHeight = 400
#WindowWidth = 500

MDIFrame=OpenWindow(0,100,100, #WindowWidth, #WindowHeight, #WINDOW_PARAMETERS ,"MDI Frame Window")

If MDIFrame
  module = LoadLibrary_("RICHED32.DLL")
  cs.CLIENTCREATESTRUCT
  MDIClient = CreateWindowEx_(#WS_EX_CLIENTEDGE, "MDIClient", "MDI Client Window", #RICHEDIT, 1, 4, #WindowWidth-10, #WindowHeight-50, MDIFrame, 0, module, cs)
  MDIChild1 = CreateWindowEx_(#WS_EX_MDICHILD , "RichEdit", "MDI Child 1 Window", #WINDOW_PARAMETERS, 10, 10, 200, 300, MDIClient, 0, module, cs)
  MDIChild2 = CreateWindowEx_(#WS_EX_MDICHILD , "RichEdit", "MDI Child 2 Window", #WINDOW_PARAMETERS, 250, 10, 200, 300, MDIClient, 0, module, cs)
EndIf

Repeat
  EventID = WaitWindowEvent()
  If EventID = #WM_PAINT
    UpdateWindow_(MDIChild1)
  EndIf
Until EventID=#PB_EventCloseWindow

End
webmatze

Registered Purebasic User.
Using Windows XP on an AMD System...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Paul.

That IS a strange result :)
It seems that as long as the windows are overlapping, they are drawn properly.

Add this before the Repeat loop to see:
SendMessage_(MDIClient,#WM_MDICASCADE,0,0)
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.

Hi WebMatze,
I had the same problem with the HTMLview code (you can see the topic under Tips & Tricks.

My code was running good on WinXP and Win98SE but not on Win2000 (thx Michael...)
Your code looks fine to me on Win98SE right now...

The problem (in my code) was the call of CreateWindowEx_ because the second parameter (from the right) is the 'handle of application instance' so it would NOT be the handle of the loaded library itself.

Michael helped me to see that and added to my code GetModuleHandle_(0) to get the instance and use it with CreateWindowEx_.
Since than my code works also Properly under Win2000.

Take a closer look at the HTMLviewer topic (also my comment on WinXP for development...) to see what I mean.
Hope this will solve your problem.
At home I have also an AMD-WinXP system


Have a nice day...
Franco

Sometimes you have to go a lonely way to accomplish genius things.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Rings.

add #WINDOW_PARAMETERS|#RICHEDIT in the CreateChildRoutine for a Editor-style.
I played around with the Windows API and the result is this little pice of code.

But there are still some bugs. The first Child Window is not painted properly.

Does anybody know what the fault is?

Code: Select all

#RICHEDIT = #WS_CHILD | #WS_VISIBLE |#WS_VSCROLL |#ES_MULTILINE |#ES_AUTOVSCROLL
#WINDOW_PARAMETERS = #PB_Window_SystemMenu

#WindowHeight = 400
#WindowWidth = 500

MDIFrame=OpenWindow(0,100,100, #WindowWidth, #WindowHeight, #WINDOW_PARAMETERS ,"MDI Frame Window")

If MDIFrame
  module = LoadLibrary_("RICHED32.DLL")
  cs.CLIENTCREATESTRUCT
  MDIClient = CreateWindowEx_(#WS_EX_CLIENTEDGE, "MDIClient", "MDI Client Window", #RICHEDIT, 1, 4, #WindowWidth-10, #WindowHeight-50, MDIFrame, 0, module, cs)
  MDIChild1 = CreateWindowEx_(#WS_EX_MDICHILD , "RichEdit", "MDI Child 1 Window", #WINDOW_PARAMETERS, 10, 10, 200, 300, MDIClient, 0, module, cs)
  MDIChild2 = CreateWindowEx_(#WS_EX_MDICHILD , "RichEdit", "MDI Child 2 Window", #WINDOW_PARAMETERS, 250, 10, 200, 300, MDIClient, 0, module, cs)
EndIf

Repeat
  EventID = WaitWindowEvent()
  If EventID = #WM_PAINT
    UpdateWindow_(MDIChild1)
  EndIf
Until EventID=#PB_EventCloseWindow

End
webmatze

Registered Purebasic User.
Using Windows XP on an AMD System...
Getting better with a little help from my friends....thx Siggi
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

Thsi is a bit more complete, but is far from a complete MDI application. I've been playing with MDI to code an MDI library, but I couldn't make the child windows maximize properly, that is, with the buttons in the title bar. Does someone have a solution for that?

Code: Select all

#RICHEDIT = #WS_CHILD|#WS_VISIBLE|#WS_VSCROLL|#ES_MULTILINE|#ES_AUTOVSCROLL|#ES_NOHIDESEL
#WINDOW_PARAMETERS = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget
#WindowHeight = 400
#WindowWidth = 500
cs.CLIENTCREATESTRUCT
hWindowMenu = CreateMenu(0)
cs\idFirstChild = 100
If hWindowMenu
  MenuTitle("&File")
    MenuItem(0, "&Open")
    MenuBar()
    MenuItem(1, "&Quit")
  MenuTitle("&Windows")
    MenuItem(2, "Tile")
EndIf
cs\hWindowMenu = GetSubMenu_(hWindowMenu, 1)

MDIFrame = OpenWindow(0,100,100, #WindowWidth, #WindowHeight, #WINDOW_PARAMETERS ,"MDI Frame Window")

If MDIFrame
  AttachMenu(0, WindowID())
  module = GetModuleHandle_(0)
  If LoadLibrary_("RICHED20.DLL")
    RichClass.s = "RichEdit20A"
  Else
    If LoadLibrary_("RICHED32.DLL")
      RichClass.s = "RichEdit"
    Else
      MessageRequester("Error", "RichEdit Windows library not present.", 0)
      End
    EndIf
  EndIf
  MDIClient = CreateWindowEx_(#WS_EX_CLIENTEDGE, "MDIClient", "MDI Client Window", #RICHEDIT, 1, 4, #WindowWidth-10, #WindowHeight-50, MDIFrame, 0, module, @cs)

  MDIChild1 = CreateMDIWindow_(RichClass, "MDI Child 1", #RICHEDIT, 10, 10, 200, 300, MDIClient, module, 0)
  MDIChild2 = CreateMDIWindow_(RichClass, "MDI Child 2", #RICHEDIT, 250, 10, 200, 300, MDIClient, module, 0)
 
EndIf

Repeat

  EventID = WaitWindowEvent()
  If EventID = #WM_PAINT
    UpdateWindow_(MDIChild1)
  EndIf
Until EventID = #PB_EventCloseWindow

End
Let's see if we can give PureBasic MDI capabilities! Bye,

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by cor.

Nice work

What about the the following:

How to copy image from CreateImage command to the richedit child window?

Using Windows 98 SE
Registered PB version : 2.90 (Windows)
--------------------------
C. de Visser
Author of Super Guitar Chord Finder
http://www.ready4music.com
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by webmatze.

To maximize a child Window you can use

Code: Select all

 SendMessage_(MDIClient, #WM_MDIMAXIMIZE, MDIChild1,0)
To Cascade use

Code: Select all

 SendMessage_(MDIClient,#WM_MDICASCADE,0,0)
and to activate use

Code: Select all

 SendMessage_(MDIClient, #WM_MDIACTIVATE, MDIChild1,0)
By the way...

if I click on a child window or if I use #WM_MDIACTIVATE - the titlebar of the active child window is still not highlighted

that's strange

Registered Purebasic User.
Using Windows XP on an AMD System...
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

The #WM_MDIACTIVATE must be processed or passed using DefFrameProc or DefMDIChildProc, I don't remember. I have a complete MDI message processing code, but I don't want to get into it until the "maximize child window" problem is solved.

Your code maximizes the MDI child window but still doesn't put its close/maximize buttons in the menu bar, I don't know if I explain myself. It is maximized only within in the client window area.

Bye,

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.
The #WM_MDIACTIVATE must be processed or passed using DefFrameProc or DefMDIChildProc, I don't remember. I have a complete MDI message processing code, but I don't want to get into it until the "maximize child window" problem is solved.
I'm sorry for you El_Choni, but I suppose you have to.
I have code for another language and they use after creating the MDIChild following code:
(translated for your PureBasic code...)

; -21 = GWL_USERDATA
; -4 = GWL_WNDPROC
SetWindowLong_(MDIChild1,-21,GetWindowLong_(MDIChild1,-4))
SetWindowLong_(MDIChild1,-4,MDIChildProc) ; MDIChildProc is AFAIK a structure

If I comment this two lines the MDIChildWindow acts like in your code (not really maximized, you know what I mean).
And I can understand that because the 3 buttons (min/max/close) are, if you maximize the MDIChildWindow a part of your MDIFrame, so you have to replace some events and so forth.
I'm not a specialist in MDI but I hope this helps.


Have a nice day...
Franco

Sometimes you have to go a lonely way to accomplish genius things.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.
To maximize a child Window you can use

Code: Select all

 SendMessage_(MDIClient, #WM_MDIMAXIMIZE, MDIChild1,0)
You can also use:

Code: Select all

 ShowWindow_(MDIChild1,3)


BTW: I don't get it why M$ made more than one command for the same function.
Well that's a possibility why Windows is not so lean and fast it could be


Have a nice day...
Franco

Sometimes you have to go a lonely way to accomplish genius things.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

Hi, made some progress but still far from the desired behavior:

Code: Select all

#RICHEDIT = #WS_CHILD|#WS_VISIBLE|#WS_VSCROLL|#ES_MULTILINE|#ES_AUTOVSCROLL|#ES_NOHIDESEL
#WINDOW_PARAMETERS = #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget
#WindowWidth = 480
#WindowHeight = 320

#IDR_CHILDMENU = 102
#IDM_EXIT = 40001 
#IDM_TILEHORZ = 40002 
#IDM_TILEVERT = 40003
#IDM_CASCADE = 40004 
#IDM_NEW = 40005 
#IDM_CLOSE = 40006

DisableDebugger

; Not being called, but should be

Procedure.l MDIChildProc(hWnd.l, uMsg.l, EventwParam.l, EventlParam.l)
  Select uMsg
    Case #WM_MDIACTIVATE
      Select EventlParam
        Case hWnd
          SendMessage_(MDIClient, #WM_MDISETMENU, hChildMenu, GetSubMenu_(hChildMenu, 1))
        Default
          SendMessage_(MDIClient, #WM_MDISETMENU, hMainMenu, GetSubMenu_(hMainMenu, 1))
      EndSelect
      DrawMenuBar_(MDIFrame)
    Default
      DefMDIChildProc_(hWnd, uMsg, EventwParam, EventlParam)
  EndSelect
  result = 0
  ProcedureReturn result
EndProcedure

EnableDebugger

If CreateMenu(0)
  MenuTitle("&File")
    MenuItem(0, "&New")
    MenuBar()
    MenuItem(1, "&Close")
    MenuBar()
    MenuItem(2, "&Quit")
  MenuTitle("&Windows")
    MenuItem(3, "Tile horizontal")
    MenuItem(4, "Tile vertical")
    MenuItem(5, "Cascade")
EndIf

MDIFrame = OpenWindow(0,100,100, #WindowWidth, #WindowHeight, #WINDOW_PARAMETERS ,"MDI Frame Window")

If MDIFrame
  AttachMenu(0, WindowID())
  hInstance = GetModuleHandle_(0)
  If LoadLibrary_("RICHED20.DLL")
    RichClass.s = "RichEdit20A"
  Else
    If LoadLibrary_("RICHED32.DLL")
      RichClass.s = "RichEdit"
    Else
      MessageRequester("Error", "RichEdit Windows library not present.", 0)
      End
    EndIf
  EndIf

  hChildMenu = LoadMenu_(hInstance, #IDR_CHILDMENU)
  hMainMenu = GetMenu_(MDIFrame)
  ShowWindow_(MDIFrame, #SW_SHOWNORMAL)

  cs.CLIENTCREATESTRUCT
  cs\hWindowMenu = GetSubMenu_(hMainMenu, 1)
  cs\idFirstChild = 100
  
  MDIClient = CreateWindowEx_(#WS_EX_CLIENTEDGE, "MDIClient", "MDI Client Window", #RICHEDIT, 1, 4, #WindowWidth-10, #WindowHeight-50, MDIFrame, 0, hInstance, @cs)

  MDIChildTitle.s = "MDI Child"

  mdc.MDICREATESTRUCT
  mdc\szClass = @RichClass
  mdc\szTitle = @MDIChildTitle
  mdc\hOwner = hInstance
  mdc\x = #CW_USEDEFAULT 
  mdc\y = #CW_USEDEFAULT 
  mdc\lx = #CW_USEDEFAULT 
  mdc\y = #CW_USEDEFAULT 
  mdc\style = #RICHEDIT
  mdc\lParam = 0

EndIf

Repeat

  uMsg = WaitWindowEvent()
  hWnd = EventWindowID()
  EventwParam = EventwParam()
  EventlParam = EventlParam()

  Select uMsg
    Case #PB_EventMenu
      Select EventMenuID()
        Case 0 ; New
          SendMessage_(MDIClient, #WM_MDICREATE, 0, @mdc)
;          SetWindowLong_(SendMessage_(MDIClient, #WM_MDICREATE, 0, @mdc), #GWL_WNDPROC, @MDIChildProc()) ; This crashes the app, should call MDIChildProc()
        Case 1 ; Close
          If MessageBox_(hWnd, "Are you sure you want to close this window?", "Win32asm MDI Demo", #MB_YESNO) = #IDYES
            SendMessage_(MDIClient, #WM_MDIDESTROY, SendMessage_(MDIClient, #WM_MDIGETACTIVE, 0, 0), 0) ; Not working, should close MDI child
          EndIf
        Case 2 ; Quit
          Quit = 1
        Case 3 ; Tile horizontal
          SendMessage_(MDIClient, #WM_MDITILE, #MDITILE_HORIZONTAL,0)
        Case 4 ; Tile vertical
          SendMessage_(MDIClient, #WM_MDITILE, #MDITILE_VERTICAL,0)
        Case 5 ; Cascade
          SendMessage_(MDIClient, #WM_MDICASCADE, #MDITILE_SKIPDISABLED, 0)
      EndSelect
    Default
      If uMsg#WM_CREATE And uMsg#WM_DESTROY
        If uMsg=#WM_COMMAND
          lParam.w = PeekW(EventlParam+2)
          If lParam#IDM_EXIT And lParam#IDM_TILEHORZ And lParam#IDM_TILEVERT And lParam#IDM_CASCADE And lParam#IDM_NEW And lParam#IDM_CLOSE
            result = DefFrameProc_(hWnd, MDIClient, uMsg, EventwParam, EventlParam)
          EndIf
        Else 
          DefFrameProc_(hWnd, MDIClient, uMsg, EventwParam, EventlParam)
        EndIf
      EndIf
  EndSelect

Until uMsg = #PB_EventCloseWindow

End
El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by MrVainSCL.

Hi El_Choni
Nice example and gui handling... Btw i think i found a small bug...!? When open some NEW
projects (Windows) and close one by clicking on the CloseGadget... Now try to open a new window and as you should see, the numbers of windows (1,2,3...) are wrong and will not updated from now...

PIII450, 256MB Ram, 6GB HD, RivaTNT, DirectX8.1, SB AWE64, Win98SE + Updates...

greetz
MrVainSCL! aka Thorsten
Post Reply