Author Topic: Dynamic Layout  (Read 1107 times)

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Dynamic Layout
« on: January 13, 2020, 08:42:02 AM »
Hi
Tired of writing every time boring code to reposition the controls of a resizeable dialog, I remembered I had seen some solutions a while ago. Searching on the net, I quickly came to the "Dynamic Layouts" implemented as part of MFC.
The idea is simple and robust, so I decided to implement if by myself. It took me some hours and I came to a nice and simple piece of code, that I want to share here.

The description of the functionality can be read on some places in the net, e.g. https://docs.microsoft.com/en-us/cpp/mfc/dynamic-layout?view=vs-2019.

This solution is applicable to any type of window, not being restricted only to dialogs.

The code I post is using ObjAsm, but it can easily be converted to regular MASM.
Also attached is a 64 bit binary file that shows how it works. Run the application and press F2 to display the test dialog box. The size of this window can be changed and the controls are repositioned according to the parameters in the definition structures (ChildWndInfo).
 
Code: [Select]
.data
align ALIGN_DATA
ChildrenInfo label ChildWndInfo
ChildWndInfo {{}, {100, 100, 000, 000}}
ChildWndInfo {{}, {000, 000, 100, 100}}
ChildWndInfo {{}, {000, 000, 000, 000}}
ChildWndInfo {{}, {000, 000, 000, 000}}
ChildWndInfo {{}, {000, 000, 100, 100}}
ChildWndInfo {{}, {100, 100, 000, 000}}

The calling code is
Code: [Select]
New DLW::DynLayDlgModal
OCall DLW::DynLayDlgModal.Init, xsi, [xsi].hWnd, 1000, offset ChildrenInfo
OCall DLW::DynLayDlgModal.Show
OCall DLW::DynLayDlgModal.Done
xor eax, eax

Biterider

jj2007

  • Member
  • *****
  • Posts: 10464
  • Assembler is fun ;-)
    • MasmBasic
Re: Dynamic Layout
« Reply #1 on: January 13, 2020, 03:57:37 PM »
Nice :thumbsup:

Attached my demo for comparison (with 24 lines of source). Extract the files to a folder and run the exe :wink2:

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Re: Dynamic Layout
« Reply #2 on: January 13, 2020, 06:26:02 PM »
Hi jj
Nice to see that you went a similar way  :thumbsup:
I tried to mimic the MS implementation as much as possible. One difference is that MS stores the control paramters in the resource data section while I do it in the data section. This allows me to change them on the fly if necessary.

One of the original ideas behind "Dynamic Layouts" is that controls should not overlap or disappear to maintain all functionality. In real world applications, WM_GETMINMAXINFO should be used to limit the minimum window/dialog size. This can be achieved using some predefined values or the initial size, allowing only to grow.

There is a very nice updated MS document that specifies what a Windows-compliant layout should look like https://docs.microsoft.com/en-us/windows/win32/uxguide/vis-layout. Older versions like the original Win32 can be found here https://docs.microsoft.com/en-us/previous-versions/windows/desktop/bb226818%28v%3Dvs.85%29 which is still valid. If you look around these places you will also find useful information.

Side note: have you noticed the rendering problem on your demo when the controls overlap?

Biterider

jj2007

  • Member
  • *****
  • Posts: 10464
  • Assembler is fun ;-)
    • MasmBasic
Re: Dynamic Layout
« Reply #3 on: January 13, 2020, 08:02:24 PM »
Nice links, thanks. The M$ rules make sense, but I would respect them more if all those nicely styled dialog boxes by Windows would actually do what they promise to do. Worst example imho is Windows "help". In 90% of all cases, it's just a waste of time :biggrin:

Re rendering: You can even make the menu disappear when you squeeze it vertically - that's Windows. WM_GETMINMAXINFO is indeed an option, but I often trust the user :wink2:

HSE

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Dynamic Layout
« Reply #4 on: January 13, 2020, 11:29:45 PM »
Attached my demo for comparison

Last RichMasm is failing to translate *.asc to *.asm:
Code: [Select]
°B5GuiParas equ "Dynamic Layout Demo", y100, w900, h400, m9, bGrey ; x at 999px, y at 100px, width 900px, margin 9px, grey background
°B4GuiMenu equ @File, &Open, &Save, -, E&xit, @Whatever, Добро пожаловать, مرحبا بكم, Functions not implemented ; creates a menu -> Event Menu

And something else:
Code: [Select]
\jj\DynamicLayout>asmc28d /coff dynamicLayout2.asm
Asmc Macro Assembler Version 2.28.16
Copyright (C) The Asmc Contributors. All Rights Reserved.
Portions Copyright (C) 1984-2002 Sybase, Inc. All Rights Reserved.

 Assembling: dynamicLayout2.asm
*** MasmBasic version 13.12.2019 ***
## MasmBasic GUI build ##
## creating 11 controls ##
dynamicLayout2.asm(24) : error A2052: forced error : ### GuiEnd/EndOfCode option XP works only with polink, sorry ###


jj2007

  • Member
  • *****
  • Posts: 10464
  • Assembler is fun ;-)
    • MasmBasic
Re: Dynamic Layout
« Reply #5 on: January 14, 2020, 01:51:52 AM »
That's Utf8 seen with a plain text editor. You should directly use the *.asc file. But even if you insist to use the plain text *.asm, it will build fine from qEditor with a little trick: extract the attached bldall.bat as \Masm32\bin\bldall.bat, make sure you have UAsm64 in \Masm32\bin and off it goes... unfortunately, the latest versions of AsmC have problems with the type keyword :sad:

If you prefer ML and link.exe, you can remove the XP after GuiEnd. The syslink won't work then, though.

HSE

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Dynamic Layout
« Reply #6 on: January 14, 2020, 02:46:11 AM »
the latest versions of AsmC have problems with the type keyword
No problem with AsmC. Beside I'm using my building of version 2.28 with more macro levels, previous to the type thing.

That's Utf8 seen with a plain text editor.
Yes RichMasm is failing in translation. Some rtf "protect" tags are the problem.

The syslink won't work then, though.
Correct. Don't work with any linker. Perhaps some resource file is missing.

jj2007

  • Member
  • *****
  • Posts: 10464
  • Assembler is fun ;-)
    • MasmBasic
Re: Dynamic Layout
« Reply #7 on: January 14, 2020, 05:19:09 AM »
Yes RichMasm is failing in translation. Some rtf "protect" tags are the problem.

RichMasm exports a plain text file to feed the assembler. The sequence you see is Utf8. On my machine (Win7-64), Notepad shows the correct Russian and Arabic text. Wordpad, qEditor and even RichMasm rely on the Utf8 BOM (there is none because ML.exe doesn't like it) and therefore show garbage. MS Word asks you which encoding you want and suggests correctly Utf8.

E&xit, @Whatever, Добро пожаловать, مرحبا بكم, Functions

Quote
Don't work with any linker. Perhaps some resource file is missing.
It works only with one recent versions of PoLink (21.3.2015), and no resource file is used. Check the @AddManifest MACRO in \Masm32\MasmBasic\Res\DualMacs.asm
« Last Edit: January 16, 2020, 09:56:25 AM by jj2007 »

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Dynamic Layout - ObjAsm Design Considerations
« Reply #8 on: January 16, 2020, 08:55:01 AM »
Hi
After thinking about how to integrate this new feature into the existing object hierarchy, I first came to the conclusion that we could use a MessageInterceptor-derived object. It could be attached to any existing object and it automatically would become the new behaviour. However, this solution has a few pitfalls, in particular with dialogs.  :sad:

The alternative is to integrate the code in a base object like WinPrimer. Since not all WinPrimer derived objects require this functionality, we will use the Window object, whose ancestor is WinPrimer and adjust the object hierarchy.
This way, only objects that derive from Window will become the layout feature, like WinApp, SdiApp, etc. and all dialogs.  :icon_idea:

After reorganizing the inheritance tree and I modified the last example to show how it works on the SdiApp and the dialog objects. The new binary is attached.

In the implementation I added a header to the array of definition structures to add information about the min and max size and some flags. As a convenience, a gripper can be added.  :cool:

Biterider

jj2007

  • Member
  • *****
  • Posts: 10464
  • Assembler is fun ;-)
    • MasmBasic
Re: Dynamic Layout
« Reply #9 on: January 16, 2020, 09:40:49 AM »
Looks good but the dialog flickers a bit when resizing.

Siekmanski

  • Member
  • *****
  • Posts: 2279
Re: Dynamic Layout
« Reply #10 on: January 16, 2020, 10:49:16 AM »
Works OK, when resizing ( Win 8.1 ) no flicker.
Creative coders use backward thinking techniques as a strategy.

HSE

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Dynamic Layout - ObjAsm Design Considerations
« Reply #11 on: January 17, 2020, 12:32:51 AM »
Hi Biterider!

After thinking about how to integrate this new feature into the existing object hierarchy

You can make that optional.

As extreme example I have an application with 18 switch (not counting ObjAsm switches). That means I can build same application in at least 18 different ways, making assembled application smaller as possible.

I'm thinking that some objects could include some switches because they have functions rarely used.

Regards. HSE.

HSE

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Dynamic Layout
« Reply #12 on: May 21, 2020, 01:52:33 AM »
Hi Biterider!!

How you can resize the Static in the example?

Thanks. HSE

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 533
  • ObjAsm Developer
    • ObjAsm
Re: Dynamic Layout
« Reply #13 on: May 21, 2020, 03:09:43 AM »
Hi HSE
In the DLApp_Main.inc file change:
Code: [Select]
; ——————————————————————————————————————————————————————————————————————————————————————————————————
; Method:     DLApp.Init
; Purpose:    Initialize the SDI application object.
; Arguments:  None.
; Return:     Nothing.

.data
align ALIGN_DATA
AppChildrenInfo label DL_HEADER
DL_HEADER     {DLF_LOAD_MIN_INISIZE or DLF_USE_MINSIZE or DLF_ADD_GRIPPER, \
               {}, {300, 200}, {}}
DL_CHILD_INFO {{50, 50, 50, 50}}      ;Watermark parameter   ***** change here *****

WATERMERK_WIDTH   equ 180
WATERMERK_HEIGHT  equ 045

In the original file I placed too much DL_CHILD_INFO structures. Probably while I was experimenting with other windows and forgot to remove them.
Remember that the gripper don't need such a structure, but all other child windows do.


Play with the parameter an you will see how they work.  The complete functionality and some explanatory comments can be found in the Window.inc file.

Biterider

HSE

  • Member
  • *****
  • Posts: 1349
  • <AMD>< 7-32>
Re: Dynamic Layout
« Reply #14 on: May 21, 2020, 04:36:55 AM »
Thanks :thumbsup:

I have the idea.

My imagination still is short to figure out what You are trying to achieve using a delta instead of a proportion  :biggrin: Don't look very well for me.