Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Layout in Win32 GUI program

Tags:

c++

winapi

I have a sort of abstract question about using straight Win32 for GUI programming. As my only previous GUI experience has been in Java using Swing I'm used to having a layout manager that automatically resizes/repositions buttons and stuff when a window is resized. Is there something similar that comes built in to the Win32 API, or does one have to manually recalculate sizes and positions using absolute locations on every repaint? I assume that this is in fact the way to do it because I haven't stumbled across anything that looks like layout management in the MSDN docs, but as those are (to my mind) a tad labyrinthine I may have missed it.

Thanks for your help!

like image 541
Nathan McCrina Avatar asked Apr 04 '12 02:04

Nathan McCrina


People also ask

What is layout in window?

Layout is the sizing, spacing, and placement of content within a window or page. Effective layout is crucial in helping users find what they are looking for quickly, as well as making the appearance visually appealing.

What is Win32 C++?

Win32++ - "Win32++ is a C++ library used to build windows applications. Win32++ is a free alternative to MFC. It has the added advantage of being able to run on a wide range of free compilers, including Visual Studio Community, and the MinGW compiler provided with CodeBlocks and Dev-C++."

How do I use Windows API?

To call a Windows API using the DllImport attributeOpen a new Windows Application project by clicking New on the File menu, and then clicking Project. The New Project dialog box appears. Select Windows Application from the list of Visual Basic project templates. The new project is displayed.


2 Answers

You need to take a look at ATL (shipped with Visual C++), and correspondingly, WTL (not shipped, need to download).

They compile almost completely to "straight Win32", while providing a nice C++ wrapper around them. They are very lightweight (almost no weight, actually -- it's direct Win32 for 99% of the calls), and yet WTL is designed to mimic MFC's features, so it's still pretty featureful.

You need to be semi-good with C++, though.

The easiest way is to use CDialogResize<CYourDialog> in something like

// Put ATL includes before here..
#include <atlcrack.h>  // Include this from WTL for message map
#include <atlframe.h>  // Include this from WTL for CDialogResize

class CYourDialog : CDialogImpl<CYourDialog>, CDialogResize<CYourDialog>
{
    BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam)
    {
        this->DlgResize_Init();                     // Initialize the positions
    }

    BEGIN_MSG_MAP_EX(CYourDialog)  // Learn about message maps if you haven't
        MSG_WM_INITDIALOG(OnInitDialog)
        CHAIN_MSG_MAP(CDialogResize<CYourDialog>)   // Chain to the parent
    END_MSG_MAP()

    BEGIN_DLGRESIZE_MAP(CYourDialog)
        DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_Y)        // Layout for "OK" button
    END_DLGRESIZE_MAP()
};

DLGRESIZE_CONTROL() is the heart of the layout -- DLSZ_MOVE_Y, for example, says that you want to move IDOK vertically. You can also group them, but it gets tricky (sometimes I don't understand what's going on either)... but once you get it right, it's actually not that bad. :)


Here's a self-contained example:

#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

#include <atlbase.h>
extern CComModule _Module;
#include <atlapp.h>
#include <atlcrack.h>
#include <atlwin.h>
#include <atlframe.h>
#include "resource.h"

class CMyDialog : public CDialogImpl<CMyDialog>, CDialogResize<CMyDialog>
{
public:
    enum { IDD = IDD_DIALOG1 };

private:
    BOOL OnInitDialog(CWindow wndFocus, LPARAM)
    {
        this->DlgResize_Init();
        return TRUE;
    }

    void OnOK(UINT, int, HWND) { this->EndDialog(ERROR_SUCCESS); }
    void OnCancel(UINT, int, HWND) { this->EndDialog(ERROR_CANCELLED); }

    BEGIN_MSG_MAP_EX(CMyDialog)
        MSG_WM_INITDIALOG(OnInitDialog)
        COMMAND_HANDLER_EX(IDOK, BN_CLICKED, OnOK)
        COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnCancel)
        CHAIN_MSG_MAP(CDialogResize<CMyDialog>)
    END_MSG_MAP()

    BEGIN_DLGRESIZE_MAP(CMyDialog)
        DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_X | DLSZ_MOVE_Y)
        DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_X | DLSZ_MOVE_Y)
    END_DLGRESIZE_MAP()
};

CComModule _Module;

int WINAPI _tWinMain(
    HINSTANCE hInstance, HINSTANCE hInstPrevious,
    LPTSTR lpCmdLine, int nCmdShow)
{
    _Module.Init(NULL, hInstance);
    {
        CMyDialog dialog;
        dialog.DoModal();
    }
    _Module.Term();
}

To compile it, you also need a file named resource.h with the following contents in the same project folder:

#define IDD_DIALOG1                     101
#define IDR_RT_MANIFEST1                103

And a file named Sample.rc added to the project, which can be edited with Visual Studio and which contains the dialog layout:

#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif
#ifdef APSTUDIO_INVOKED
1 TEXTINCLUDE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "\r\n"
    "\0"
END
#endif
IDD_DIALOG1 DIALOGEX 0, 0, 316, 180
STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
EXSTYLE WS_EX_APPWINDOW
CAPTION "Dialog"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,205,159,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,259,159,50,14
END
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO 
BEGIN
    IDD_DIALOG1, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 309
        TOPMARGIN, 7
        BOTTOMMARGIN, 173
    END
END
#endif
#endif
#ifndef APSTUDIO_INVOKED
#endif
like image 64
user541686 Avatar answered Oct 07 '22 13:10

user541686


No. The Win32 API doesn't include code to resize and reposition controls. You have to write your own or use a library. Microsoft offers a resource editor in Visual Studio, and MFC (a C++ wrapper around the API), but neither of those address your actual problem (resize and reposition automatically) either. I have used wxWidgets, which is a lot more coherent than MFC (in my opinion) and has a concept called "sizers" which does address resize and reposition.

like image 37
Bill Forster Avatar answered Oct 07 '22 14:10

Bill Forster