News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

How to resize dialog dynamically?

Started by Mikl__, June 04, 2024, 10:08:28 AM

Previous topic - Next topic

Mikl__

Hi, all!
I'm writing a video player on masm64. For the player to work properly, you will need to install video codecs. I have k-lite megapack installed. The basis of the video player is a dialogue with control buttons and trackbars for controlling volume and navigating through a video fragment. When playing a video file, different ratios of the height and width of a video fragment are possible; in addition, the player properties assume the modes "Custom size (the user changes the size of the height and width of the video fragment as he needs)", "1/2 (height size and the width of the video fragment is halved)", "Original size (the size of the height and width of the video fragment does not change)", "Double size (the size of the height and width of the video fragment is doubled)", "Full screen mode". Playback occurs on the EDIT or STATIC element. How can I change the size of the dialog so that trackbars (volume and duration) and control buttons remain below the screen?

NoCforMe

Welll, that would be
    INVOKE  SetWindowPos, DialogHandle, 0, 0, 0, newWidth, newHeight, SWP_NOMOVE or SWP_NOZORDER
but you already knew that, right?

Of course, you'll have to move the controls (stuff below the video window) around as well, using the same function.

Assembly language programming should be fun. That's why I do it.

zedd151

What I would do Mikl__ is to use a static control to contain everything in the bottom of half the window (below the video display) as the control parent for those controls. The main window would be the parent of that static control.

Now when resizing, you only need to adjust the position of that static control. All the controls within it, will keep the same positioning relative to one another, without having to calculate the new positions for all of those controls.

It is much easier to do this with a window than a dialog box, imo.
:undecided:

NoCforMe

That's actually not a bad idea: create a "container" for all those controls. You'll have to relay messages from the container back up to the parent** (the dialog), but that's not hard to do. Make the static (probably the easiest class to deal with) invisible, and all the controls within its children. That way, you'll probably only have to set a new Y-position for the container, and leave X alone. (Just slide everything down.)

BTW, remember that a dialog is a just a window, and in many ways (not all) can be dealt with just like any other window.

** Or you can re-parent the controls to the dialog, once you've moved everything around, using SetParent(). Still easier than having to calculate all those positions.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Well, I'm sorry if I sounded confident that this would be easy to do.
Apparently it's not.
I tried making a container (static) in a dialog, putting some controls inside it, making them children of the container, then moving the container.
The container moved. But the children all disappeared!
Apparently the dialog manager is doing some stuff behind the scenes that interferes with this working.

Quote from: sudoku on June 04, 2024, 10:55:30 AMWhat I would do Mikl__ is to use a static control to contain everything in the bottom of half the window (below the video display) as the control parent for those controls. The main window would be the parent of that static control.

So sudoku, have you actually done this? Did you use a dialog or just a main window that you created with CreateWindowEx()? What was the parent-child relationship of all the windows?

This is a lot trickier than I had anticipated.
Assembly language programming should be fun. That's why I do it.

zedd151

It was definitely not a dialog box. That's why I said much easier to do a window. I didn't even think of attempting it with a dialog.

What I did was create a custom toolbar of sorts, with (search, replace, goto line, etc) for an editor I made several years back. If I can find the code, I'll post it later. (At least the relevant parts)

That wasn't real easy to do either, but I did manage to make it all work, in the end.

Another way to do it, is to use the rectangle (bottom, left) of the video display as a reference in placing all of the other controls, rather than from the dialog box top, left. Assuming that when resizing, the video would be resized before the controls...
:undecided:

zedd151

#6
The search functions' controls are all within a "container" static control, which is the parent of the child controls.

Attached .zip file removed, as it is no longer needed.
:undecided:

NoCforMe

OK. I'm trying a different approach, which is to move each and every child control independently. Which could be a pain in the ass, but I think I've got a couple routines mapped out that would take most of the pain out (the position calculations would be done automagically). This would use the BeginDeferWindowPos() - DeferWindowPos() - EndDeferWindowPos() sequence to move stuff around.

We'll see.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Got it!

Check out the attached testbed. This is a dialog with some controls in it that can be shifted down or up.

I gave up on sudoku's idea of using a container window, which would have been nice if I could have gotten it to work. (But actually it would probably have been much more hassle even if it did work.)

The scheme I used is dumbassed (move each and every control individually), but I invented two routines that make it easy for the programmer:
  • AddChildInfo() adds a control to a list of controls to be moved
  • ShiftControls(moveDirection) moves them all up or down as a block

I used the BeginDeferWindowPos() - DeferWindowPos() - EndDeferWindowPos() sequence here, which simplifies things somewhat. (It's kind of a wrapper around SetWindowPos() that stages the moves, then moves everything all at once.)

My example just moves everything down or up by a fixed amount. This scheme could easily be adapted to move the block of controls to several different positions (say if the video-display window can have several different heights). It could even be adapted with not too much trouble to move things sideways (in the X-direction) as well.

So far as programming details go, the only extra pain the programmer has to go through is this. In the dialog's WM_INITDIALOG handler, do this for each control you want to move:
INVOKE GetDlgItem, hWin, $button1
MOV Button1Handle, EAX
INVOKE AddChildInfo, EAX, hWin

Then when it comes time to move stuff, set the move direction variable (0=down, 1=up) and do this:
INVOKE ShiftControls, ShiftDirection
Easy peasy.

Assembly language programming should be fun. That's why I do it.

jj2007

Attached an example of resizable controls. The source (77 lines) sits in \Masm32\MasmBasic\Res\SkelGui.asc in case you have MasmBasic installed.

NoCforMe

Nice, I guess, but all that seems to do is respond to WM_SIZE appropriately.
The topic here is moving controls around.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Quote from: Mikl__ on June 04, 2024, 10:08:28 AMHow can I change the size of the dialog so that trackbars (volume and duration) and control buttons remain below the screen?

Mikl,
If you want to try my method to move controls down in your dialog, here's everything you need to do that. It's not too painful. There are two routines (AddChildInfo() and ShiftControls()) that do all the heavy lifting for you.

Let me know if this works for you.

;=====================================================
; Everything needed to move child controls in a dialog
;=====================================================

MoveChildControl PROTO ctrlHandle:HWND, moveDistance:DWORD
AddChildInfo PROTO ctrlHandle:HWND, dlgHandle:HWND

CTRLINFO STRUCT
  handle HWND ?
  x DD ?
  y DD ?
CTRLINFO ENDS

$shiftDistance EQU 60
$shiftDown EQU 0
$maxCtrls EQU 64

.data

CtrlInfoPtr DD CtrlInfo

.data?

NumChildCtrls DD ?

; Array of CTRLINFO structures for moving child controls:
CtrlInfo CTRLINFO $maxCtrls DUP (<>)

ShiftDirection DD ? ;0 = shift down, 1 = shift up.

.code

;====================================
; Shift all controls down or up:
;====================================
do_shift:
INVOKE ShiftControls, ShiftDirection

;=====================================
; Dialog initialization (WM_INITDIALOG)
;=====================================
do_init:
; Add child controls to be moved to move list, using AddChildInfo():
INVOKE GetDlgItem, hWin, $button1
INVOKE AddChildInfo, EAX, hWin
INVOKE GetDlgItem, hWin, $button2
INVOKE AddChildInfo, EAX, hWin
INVOKE GetDlgItem, hWin, $button3
INVOKE AddChildInfo, EAX, hWin
INVOKE GetDlgItem, hWin, $button4
INVOKE AddChildInfo, EAX, hWin
INVOKE GetDlgItem, hWin, $static1
INVOKE AddChildInfo, EAX, hWin
INVOKE GetDlgItem, hWin, $edit1
INVOKE AddChildInfo, EAX, hWin


;====================================
; ShiftControls (moveDirection)
;
; After child-control list is filled in,
; goes through list and moves them to new
; position depending on "moveDirection".
;====================================

ShiftControls PROC moveDirection:DWORD
LOCAL dwpHandle:HANDLE, numCtrls:DWORD

PUSH EBX

; Create deferred-window-move list:
INVOKE BeginDeferWindowPos, NumChildCtrls
MOV dwpHandle, EAX

; Now go through list and set new window positions (deferred):
MOV EBX, OFFSET CtrlInfo

MOV ECX, NumChildCtrls
wploop: PUSH ECX

; If move direction is down, add to control's original Y-position, otherwise use it as-is:
MOV EAX, [EBX].CTRLINFO.y
CMP moveDirection, $shiftDown
JNE @F
ADD EAX, $shiftDistance

@@: INVOKE DeferWindowPos, dwpHandle, [EBX].CTRLINFO.handle, HWND_TOP, [EBX].CTRLINFO.x, EAX, 0, 0,
SWP_NOSIZE or SWP_SHOWWINDOW
MOV dwpHandle, EAX ;Store updated handle for next time.
ADD EBX, SIZEOF CTRLINFO
POP ECX
LOOP wploop

POP EBX

; Finally, make the new window positions so:
INVOKE EndDeferWindowPos, dwpHandle
RET

ShiftControls ENDP


;====================================
; AddChildInfo (ctrlHandle, dlgHandle)
;
; Adds a control's info to the CTRLINFO structure
; array so it can be moved later.
;====================================

AddChildInfo PROC ctrlHandle:HWND, dlgHandle:HWND
LOCAL gpRect:RECT, pt:POINT

INVOKE GetClientRect, ctrlHandle, ADDR gpRect
MOV EAX, gpRect.left
MOV pt.x, EAX
MOV EAX, gpRect.top
MOV pt.y, EAX
INVOKE ClientToScreen, ctrlHandle, ADDR pt
INVOKE ScreenToClient, dlgHandle, ADDR pt

MOV EDX, CtrlInfoPtr
MOV EAX, ctrlHandle
MOV [EDX].CTRLINFO.handle, EAX
MOV EAX, pt.x
MOV [EDX].CTRLINFO.x, EAX
MOV EAX, pt.y
MOV [EDX].CTRLINFO.y, EAX
ADD CtrlInfoPtr, SIZEOF CTRLINFO
INC NumChildCtrls

RET

AddChildInfo ENDP

You'll need to change the constant $shiftDistance to suit your application (or make this a variable). This is the distant in screen units to move the controls.

Everything else should be pretty much self-explanatory.
Assembly language programming should be fun. That's why I do it.

Mikl__

Unfinished media player on Masm64
Before opening and running a video file, set the image size (normal, half, double or full screen) and playback rate. Attached are asm-/rc-/ico-/exe files.

Mikl__

Hi All!
So, how do you like the media player?

NoCforMe

Works nicely.
Some comments:
o Seems you can only change most settings (video size, playback speed, etc.) when you first open a file, not while video is playing.
o It wants to always stay on top; looks like there's a menu setting for this, but it's grayed out.
o Position trackbar reaches its end position before the end of the video.
o I get an exception of some kind when I close the program. Sometimes after, sometimes before the "'Bye!" message box.

Probably all things you already know about ...
Assembly language programming should be fun. That's why I do it.