Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Dialog box margins

Dialog box margins

Scheduled Pinned Locked Moved C / C++ / MFC
csharpvisual-studiowpfquestion
15 Posts 6 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Alexander Kindel
    wrote on last edited by
    #1

    I'm generating dialog templates programmatically for a win32 project. A thing I often want to do is size the dialog box such that the distance between the left edge of the client region and the left edge of the leftmost control is the same as that between the right edge of the rightmost control and the right edge of the client region. Since the size of the dialog box as specified in the template, I believe, includes the non-client area, the only way I know of to do this is to use AdjustWindowRect on a RECT representing the desired client region. Since this requires the handle of the window being adjusted, I can't do it until after the dialog has been created. So I was wondering...if I can't ensure equal margins until runtime, how is it possible that one can use the GUI editor Visual Studio provides to create dialogs with equal margins ahead of time? I want to be able to do that too.

    L M M L D 5 Replies Last reply
    0
    • A Alexander Kindel

      I'm generating dialog templates programmatically for a win32 project. A thing I often want to do is size the dialog box such that the distance between the left edge of the client region and the left edge of the leftmost control is the same as that between the right edge of the rightmost control and the right edge of the client region. Since the size of the dialog box as specified in the template, I believe, includes the non-client area, the only way I know of to do this is to use AdjustWindowRect on a RECT representing the desired client region. Since this requires the handle of the window being adjusted, I can't do it until after the dialog has been created. So I was wondering...if I can't ensure equal margins until runtime, how is it possible that one can use the GUI editor Visual Studio provides to create dialogs with equal margins ahead of time? I want to be able to do that too.

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      You can select a set of controls in the editor and then use the toolbar tool that centres the group in the dialog. There are tools to centre horizontally or vertically, make equidistant, align together etc.

      1 Reply Last reply
      0
      • A Alexander Kindel

        I'm generating dialog templates programmatically for a win32 project. A thing I often want to do is size the dialog box such that the distance between the left edge of the client region and the left edge of the leftmost control is the same as that between the right edge of the rightmost control and the right edge of the client region. Since the size of the dialog box as specified in the template, I believe, includes the non-client area, the only way I know of to do this is to use AdjustWindowRect on a RECT representing the desired client region. Since this requires the handle of the window being adjusted, I can't do it until after the dialog has been created. So I was wondering...if I can't ensure equal margins until runtime, how is it possible that one can use the GUI editor Visual Studio provides to create dialogs with equal margins ahead of time? I want to be able to do that too.

        M Offline
        M Offline
        mo1492
        wrote on last edited by
        #3

        I don't know if I'm misunderstanding your question but if you want to resize the dialog at runtime, you can calculate your control positions and use SetWindowPos(NULL, -1, -1, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); in the OnInitDialog() function. sorry if I misunderstood.

        A 1 Reply Last reply
        0
        • M mo1492

          I don't know if I'm misunderstanding your question but if you want to resize the dialog at runtime, you can calculate your control positions and use SetWindowPos(NULL, -1, -1, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); in the OnInitDialog() function. sorry if I misunderstood.

          A Offline
          A Offline
          Alexander Kindel
          wrote on last edited by
          #4

          Resizing at runtime is what I'm currently doing, and it's an acceptable solution, but if possible I would like to specify the size of the dialog in the template, which is generated before runtime, such that it's correct relative to the controls it contains to begin with, without need of resizing. The fact that the dialog editor can do this suggests that it is indeed possible somehow.

          M L 2 Replies Last reply
          0
          • A Alexander Kindel

            Resizing at runtime is what I'm currently doing, and it's an acceptable solution, but if possible I would like to specify the size of the dialog in the template, which is generated before runtime, such that it's correct relative to the controls it contains to begin with, without need of resizing. The fact that the dialog editor can do this suggests that it is indeed possible somehow.

            M Offline
            M Offline
            mo1492
            wrote on last edited by
            #5

            I did something like this a long time ago where I defined a dialog within a code module without the ui editor and I think you will have to implement the use of DLGTEMPLATE which is used to define the dialog and all of the associated controls. Take a look at InitModalIndirect() in the Mfc library dlgcore.cpp and I believe there was some needed functions in occmgr.cpp that will help to some extent. If you haven't used this structure before, it will required a bit of work. Oh yes, I'm still on V2005 so if you have the latest visual studio there may be some changes. Hope this is what you are looking for.

            1 Reply Last reply
            0
            • A Alexander Kindel

              I'm generating dialog templates programmatically for a win32 project. A thing I often want to do is size the dialog box such that the distance between the left edge of the client region and the left edge of the leftmost control is the same as that between the right edge of the rightmost control and the right edge of the client region. Since the size of the dialog box as specified in the template, I believe, includes the non-client area, the only way I know of to do this is to use AdjustWindowRect on a RECT representing the desired client region. Since this requires the handle of the window being adjusted, I can't do it until after the dialog has been created. So I was wondering...if I can't ensure equal margins until runtime, how is it possible that one can use the GUI editor Visual Studio provides to create dialogs with equal margins ahead of time? I want to be able to do that too.

              M Offline
              M Offline
              Maximilien
              wrote on last edited by
              #6

              It is impossible (*) to do. Win32 and MFC do not implement design time dynamic resizing of dialog controls, and offer no automatic run time resizing of dialog controls (other than MoveWindow and SetWindowPos ). You need to do it manually; there are many 3rd party solutions available that will manage resizing at run time. All of them sucks one way or the other.

              I'd rather be phishing!

              L 1 Reply Last reply
              0
              • A Alexander Kindel

                I'm generating dialog templates programmatically for a win32 project. A thing I often want to do is size the dialog box such that the distance between the left edge of the client region and the left edge of the leftmost control is the same as that between the right edge of the rightmost control and the right edge of the client region. Since the size of the dialog box as specified in the template, I believe, includes the non-client area, the only way I know of to do this is to use AdjustWindowRect on a RECT representing the desired client region. Since this requires the handle of the window being adjusted, I can't do it until after the dialog has been created. So I was wondering...if I can't ensure equal margins until runtime, how is it possible that one can use the GUI editor Visual Studio provides to create dialogs with equal margins ahead of time? I want to be able to do that too.

                L Offline
                L Offline
                leon de boer
                wrote on last edited by
                #7

                In standard Win32 API the dialog will be passed a WM_INITDIALOG message after it is created but before it is displayed. WM_INITDIALOG message - Windows applications | Microsoft Docs[^] You can simply do a call to GetClientRect to get the parent area and change the dialog that is what the message is for. You can also use CreateDialogIndirectParam, CreateDialogParam, DialogBoxIndirectParam, or DialogBoxParam and pass a pointer to the area or anything else you may want to do at runtime. If you have not got access to the dialogs parent window handle you can get it by using the dialog handle with GetParent function | Microsoft Docs[^] The dialog has been created and all functions on the handle work it just has not been made visible at that point. You can also move and resize your child windows by handle or ID, they have all been created but nothing is visible at that point. You can also manually add child windows if you so desire at that point. The WM_PAINT message to draw the dialog will be straight after that message and if it's a modal dialog it will then enter modal mode. I am not sure how MFC encapsulates the WM_INITDIALOG probably ONINITDIALOG or something like that.

                In vino veritas

                A 1 Reply Last reply
                0
                • M Maximilien

                  It is impossible (*) to do. Win32 and MFC do not implement design time dynamic resizing of dialog controls, and offer no automatic run time resizing of dialog controls (other than MoveWindow and SetWindowPos ). You need to do it manually; there are many 3rd party solutions available that will manage resizing at run time. All of them sucks one way or the other.

                  I'd rather be phishing!

                  L Offline
                  L Offline
                  leon de boer
                  wrote on last edited by
                  #8

                  Incorrect look at WM_INITDIALOG the message exists to do it. You simply move and resize the child windows before they become visible that is the whole point for the message to exist (read the message description). Everything is created but nothing has been drawn at that point. WM_INITDIALOG message - Windows applications | Microsoft Docs[^]

                  In vino veritas

                  M 1 Reply Last reply
                  0
                  • A Alexander Kindel

                    Resizing at runtime is what I'm currently doing, and it's an acceptable solution, but if possible I would like to specify the size of the dialog in the template, which is generated before runtime, such that it's correct relative to the controls it contains to begin with, without need of resizing. The fact that the dialog editor can do this suggests that it is indeed possible somehow.

                    L Offline
                    L Offline
                    leon de boer
                    wrote on last edited by
                    #9

                    A blank empty dialog template centred in it's parent at runtime and done the way speedbump is suggesting is coded below. It is pretty straight forward you just need to allocate global memory block as the template and you can fill the controls in at initialization

                    int DialogFromTemplate (HWND parent, int DialogWth, int DialogHt, char* DlgTitle, DLGPROC handler)
                    {
                    int nchar, ret;
                    int x, y;
                    RECT r;
                    HGLOBAL hgbl;
                    LPDLGTEMPLATE lpdt;
                    LPWORD lpw;
                    LPWSTR lpwsz;

                    GetClientRect(parent, &r); // Get parent client area
                    x = ((r.right+r.left)/2); // Calc x client centre position
                    y = ((r.bottom+r.top)/2); // Calc y client centre position

                    /\* from the client centre the dialog left is half width and top half height less \*/
                    x -= DialogWth/2;
                    y -= DialogHt/2;
                    

                    /* template size and position are in multiples of 2 .. yeah its weird */
                    x /= 2; // X client left position in template units
                    y /= 2; // Y client top position in template units

                    hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024); // Allocate memory
                    if (!hgbl) return -1; // If allocate fail exit
                    lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Lock the allocated memory
                    lpdt->style = WS_POPUP | WS_CAPTION | WS_SYSMENU; // Window style
                    lpdt->cdit = 0; // Number of controls
                    lpdt->x = x; // X position
                    lpdt->y = y; // Y psoition
                    lpdt->cx = DialogWth/2; // Window width (template units)
                    lpdt->cy = DialogHt/2; // Window height (template units)
                    lpw = (LPWORD)(lpdt + 1); // Set pointer address
                    *lpw++ = 0; // No menu
                    *lpw++ = 0; // Predefined dialog box class (by default)
                    lpwsz = (LPWSTR)lpw; // Typecast pointer
                    nchar = 1 + MultiByteToWideChar(CP_ACP, 0, DlgTitle,
                    -1, lpwsz, 50); // Title of dialog
                    lpw += nchar; // Increment by size of name
                    *lpw++ = 0; // No creation data
                    GlobalUnlock(hgbl); // Release lock on the memory block
                    ret = (int)DialogBoxIndirectParam(GetModuleHandle(0),
                    (LPDLGTEMPLATE)hgbl, parent, Handler, 0); // Create the dialog from template
                    GlobalFree(hgbl); // Free the allocated memory
                    return ret; // Return result
                    }

                    M 1 Reply Last reply
                    0
                    • L leon de boer

                      In standard Win32 API the dialog will be passed a WM_INITDIALOG message after it is created but before it is displayed. WM_INITDIALOG message - Windows applications | Microsoft Docs[^] You can simply do a call to GetClientRect to get the parent area and change the dialog that is what the message is for. You can also use CreateDialogIndirectParam, CreateDialogParam, DialogBoxIndirectParam, or DialogBoxParam and pass a pointer to the area or anything else you may want to do at runtime. If you have not got access to the dialogs parent window handle you can get it by using the dialog handle with GetParent function | Microsoft Docs[^] The dialog has been created and all functions on the handle work it just has not been made visible at that point. You can also move and resize your child windows by handle or ID, they have all been created but nothing is visible at that point. You can also manually add child windows if you so desire at that point. The WM_PAINT message to draw the dialog will be straight after that message and if it's a modal dialog it will then enter modal mode. I am not sure how MFC encapsulates the WM_INITDIALOG probably ONINITDIALOG or something like that.

                      In vino veritas

                      A Offline
                      A Offline
                      Alexander Kindel
                      wrote on last edited by
                      #10

                      What I'm doing already is setting the using the size information in the dialog template to store the size I want the client region to be, then calling GetWindowRect, AdjustWindowRect, and MoveWindow from the WM_INITDIALOG implementation. From the answers I've gotten, it sounds like this is about the most direct solution I could hope for, which is good to know.

                      L 1 Reply Last reply
                      0
                      • A Alexander Kindel

                        What I'm doing already is setting the using the size information in the dialog template to store the size I want the client region to be, then calling GetWindowRect, AdjustWindowRect, and MoveWindow from the WM_INITDIALOG implementation. From the answers I've gotten, it sounds like this is about the most direct solution I could hope for, which is good to know.

                        L Offline
                        L Offline
                        leon de boer
                        wrote on last edited by
                        #11

                        There are two parts to things positioning and scaling Let me formally centre the dialog at runtime to it's parent in WM_INITDIALOG .. it is this simple

                        RECT R1, R2;
                        GetClientRect(GetParent(Wnd), &R1); // Parent client area
                        GetWindowRect(Wnd, &R2); // Dialog area
                        SetWindowPos(Wnd, 0,
                        (R1.right+R1.left)/2 - (R2.right-R2.left)/2 , // Parent x centre - half dialog width
                        (R1.top+R1.Bottom)/2 - (R2.bottom-R2.top)/2, // Parent y centre - half dialog height
                        0, 0, // No size data
                        SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER);

                        Now if you want to centre and rescale generally you do the scale as a fraction to avoid floats so (numerator/denominator) where denominator must not be zero This usually works well because you have ( desired size / current size ) being the exact fraction

                        int Wth, Ht;
                        RECT R1, R2;
                        GetClientRect(GetParent(Wnd), &R1); // Parent client area
                        GetWindowRect(Wnd, &R2); // Dialog area
                        Wth = (R2.right-R2.left) * numerator; // Multiply dialog width by numerator
                        Wth /= denominator; // Divide dialog width by denominator
                        Ht = (R2.bottom-R2.top) * numerator; // Multiply dialog height by numerator
                        Ht /= denominator; // Divide dialog height by denominator
                        SetWindowPos(Wnd, 0,
                        (R1.right+R1.left)/2 - Wth/2 , // Parent x centre - half scaled dialog width
                        (R1.top+R1.Bottom)/2 - Ht/2, // Parent y centre - half dialog height
                        Wth, Ht, // New sizes
                        SWP_NOACTIVATE | SWP_NOZORDER);// Do not change order or activate

                        /* so if you want to scale the children windows you need to scale and move them */
                        /* now go thru each child by id (shown as xxx) and scale and move them with this */
                        RECT R3;
                        HWND cWnd = GetDlgItem(Wnd, xxxx); // Fetch and hold child handle from xxxx id
                        GetWindowRect(cWnd, &R3); // Fetch the child area
                        R3.left *= numerator; // Multiply child window left by numerator
                        R3.left /= denominator; // Divide child window left by denominator
                        R3.right *= numerator; // Multiply child window right by numerator
                        R3.right /= denominator; // Divide child window right by denominator
                        R3.top *= numerator; // Multiply child window top by numerator
                        R3.t

                        1 Reply Last reply
                        0
                        • L leon de boer

                          A blank empty dialog template centred in it's parent at runtime and done the way speedbump is suggesting is coded below. It is pretty straight forward you just need to allocate global memory block as the template and you can fill the controls in at initialization

                          int DialogFromTemplate (HWND parent, int DialogWth, int DialogHt, char* DlgTitle, DLGPROC handler)
                          {
                          int nchar, ret;
                          int x, y;
                          RECT r;
                          HGLOBAL hgbl;
                          LPDLGTEMPLATE lpdt;
                          LPWORD lpw;
                          LPWSTR lpwsz;

                          GetClientRect(parent, &r); // Get parent client area
                          x = ((r.right+r.left)/2); // Calc x client centre position
                          y = ((r.bottom+r.top)/2); // Calc y client centre position

                          /\* from the client centre the dialog left is half width and top half height less \*/
                          x -= DialogWth/2;
                          y -= DialogHt/2;
                          

                          /* template size and position are in multiples of 2 .. yeah its weird */
                          x /= 2; // X client left position in template units
                          y /= 2; // Y client top position in template units

                          hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024); // Allocate memory
                          if (!hgbl) return -1; // If allocate fail exit
                          lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Lock the allocated memory
                          lpdt->style = WS_POPUP | WS_CAPTION | WS_SYSMENU; // Window style
                          lpdt->cdit = 0; // Number of controls
                          lpdt->x = x; // X position
                          lpdt->y = y; // Y psoition
                          lpdt->cx = DialogWth/2; // Window width (template units)
                          lpdt->cy = DialogHt/2; // Window height (template units)
                          lpw = (LPWORD)(lpdt + 1); // Set pointer address
                          *lpw++ = 0; // No menu
                          *lpw++ = 0; // Predefined dialog box class (by default)
                          lpwsz = (LPWSTR)lpw; // Typecast pointer
                          nchar = 1 + MultiByteToWideChar(CP_ACP, 0, DlgTitle,
                          -1, lpwsz, 50); // Title of dialog
                          lpw += nchar; // Increment by size of name
                          *lpw++ = 0; // No creation data
                          GlobalUnlock(hgbl); // Release lock on the memory block
                          ret = (int)DialogBoxIndirectParam(GetModuleHandle(0),
                          (LPDLGTEMPLATE)hgbl, parent, Handler, 0); // Create the dialog from template
                          GlobalFree(hgbl); // Free the allocated memory
                          return ret; // Return result
                          }

                          M Offline
                          M Offline
                          mo1492
                          wrote on last edited by
                          #12

                          Looks familiar... good job :)

                          1 Reply Last reply
                          0
                          • L leon de boer

                            Incorrect look at WM_INITDIALOG the message exists to do it. You simply move and resize the child windows before they become visible that is the whole point for the message to exist (read the message description). Everything is created but nothing has been drawn at that point. WM_INITDIALOG message - Windows applications | Microsoft Docs[^]

                            In vino veritas

                            M Offline
                            M Offline
                            Maximilien
                            wrote on last edited by
                            #13

                            There are no mechanisms in MFC or Win32 to automatically place and resize controls; you have to do it manually in WM_SIZE. WM_INITDIALOG will let you place controls at runtime, yes, but that's it; there is no API that says, hey, I want to attach the left side of my edit box to the left side of the dialog.

                            I'd rather be phishing!

                            L 1 Reply Last reply
                            0
                            • M Maximilien

                              There are no mechanisms in MFC or Win32 to automatically place and resize controls; you have to do it manually in WM_SIZE. WM_INITDIALOG will let you place controls at runtime, yes, but that's it; there is no API that says, hey, I want to attach the left side of my edit box to the left side of the dialog.

                              I'd rather be phishing!

                              L Offline
                              L Offline
                              leon de boer
                              wrote on last edited by
                              #14

                              The OP didn't ask for that ... he asked for the ability to rescale a template or resource based dialog which we all do for high DPI apps because the inbuilt behaviour sucks. Also for the record there are groups of controls that will do exactly what you have described they are called docking controls all you decide is where you want the anchor when you create them. I can easily give you a group of control that will automatically anchor themselves to the left side of a dialog it's trivial and CDockablePane in particular are often run that way in a dialog.

                              In vino veritas

                              1 Reply Last reply
                              0
                              • A Alexander Kindel

                                I'm generating dialog templates programmatically for a win32 project. A thing I often want to do is size the dialog box such that the distance between the left edge of the client region and the left edge of the leftmost control is the same as that between the right edge of the rightmost control and the right edge of the client region. Since the size of the dialog box as specified in the template, I believe, includes the non-client area, the only way I know of to do this is to use AdjustWindowRect on a RECT representing the desired client region. Since this requires the handle of the window being adjusted, I can't do it until after the dialog has been created. So I was wondering...if I can't ensure equal margins until runtime, how is it possible that one can use the GUI editor Visual Studio provides to create dialogs with equal margins ahead of time? I want to be able to do that too.

                                D Offline
                                D Offline
                                David Crow
                                wrote on last edited by
                                #15

                                Alexander Kindel wrote:

                                ...size the dialog box such that the distance between the left edge of the client region and the left edge of the leftmost control is the same as that between the right edge of the rightmost control and the right edge of the client region.

                                Unless I'm way out in left field, this is what you do via the resource editor. If you have the guides enabled (Format ==> Toggle Guides), then you can drag your leftmost control to the left until it snaps to the left, and drag your rightmost control to the right until it snaps to the right. If you don't have or want the guides enabled, you can do it manually. For the leftmost control, just drag it until its left edge is at whatever X pos you want, usually 7 DLUs. For the rightmost control, take the sum of the control's width and the guide value (e.g., 7), and subtract that from the from the dialog's width. That is X pos of the control. It sounds way more complicated than it is. Back when I was doing dialog design regularly, I could do it easily. Just get within 10 DLUs visually, and then do the math on the tens place in your head. Microsoft used to adhere to these guidelines where spacing, DLUs, and such were all explained, but that may have changed.

                                "One man's wage rise is another man's price increase." - Harold Wilson

                                "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

                                "You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles

                                1 Reply Last reply
                                0
                                Reply
                                • Reply as topic
                                Log in to reply
                                • Oldest to Newest
                                • Newest to Oldest
                                • Most Votes


                                • Login

                                • Don't have an account? Register

                                • Login or register to search.
                                • First post
                                  Last post
                                0
                                • Categories
                                • Recent
                                • Tags
                                • Popular
                                • World
                                • Users
                                • Groups