2012-04-04 11 views
11

Mam pewien rodzaj abstrakcyjnego pytania o używanie prostego programowania Win32 dla GUI. Ponieważ moje jedyne wcześniejsze doświadczenie w GUI było w Javie przy użyciu Swinga, jestem przyzwyczajony do posiadania menedżera układu, który automatycznie zmienia rozmiar/zmienia położenie przycisków i innych rzeczy, gdy zmienia się rozmiar okna. Czy jest coś podobnego, co jest wbudowane w API Win32, czy trzeba ręcznie przeliczać rozmiary i pozycje przy użyciu bezwzględnych lokalizacji na każdym odświeżeniu? Zakładam, że jest to w rzeczywistości sposób, aby to zrobić, ponieważ nie natknąłem się na nic, co wygląda jak zarządzanie układem w dokumentach MSDN, ale ponieważ są to (według mnie) odrobinę labiryntu, może go nie zauważyłem.Układ w GUI programu Win32

Dzięki za pomoc!

+0

Mam kod MFC, który może być dostosowany do wywołań Win32 API: http://stackoverflow.com/a/5739620/5987 –

Odpowiedz

1

Być może trzeba zajrzeć do MFC, który jest opakowaniem wokół win32, który ukryje większość trudnych elementów w projektowaniu GUI. Dostarczy ci edytor zasobów, w którym możesz tworzyć i pozycjonować kontrolki w formie WYSIWYG.

+1

Nie wiedziałem, że MFC zawiera menedżera układu kontroli wysokiego poziomu. Chociaż nie pomaga to w zmianie ustawień po zmianie rozmiaru. –

+0

Pozycjonowanie! = Układ – Mehrdad

4

Nie. Win32 API nie zawiera kodu do zmiany rozmiaru i zmiany pozycji kontrolek. Musisz napisać własną lub skorzystać z biblioteki. Microsoft oferuje edytor zasobów w Visual Studio i MFC (opakowanie C++ wokół API), ale żaden z nich nie rozwiązuje problemu (zmienianie rozmiaru i automatyczna zmiana położenia). Użyłem wxWidgets, który jest dużo bardziej spójny niż MFC (moim zdaniem) i ma koncepcję o nazwie "sizers", która zajmuje się zmianą rozmiaru i repozycją.

+0

Dzięki za wyjaśnienie! –

4

Musisz rzucić okiem na ATL (dostarczany z Visual C++), a odpowiednio, WTL (nie wysłane, trzeba pobrać).

Kompilują się prawie całkowicie do "prostego Win32", zapewniając przy tym ładną otoczkę C++. Są bardzo lekkie (prawie no waga, w rzeczywistości - jest bezpośrednim Win32 dla 99% połączeń), a mimo to WTL jest zaprojektowany, aby naśladować funkcje MFC, więc nadal jest dość ciekawe.

Musisz jednak być w połowie dobrym z C++.

Najprostszym sposobem jest użycie CDialogResize<CYourDialog> w coś jak

// 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() jest sercem układu - DLSZ_MOVE_Y, na przykład, twierdzi, że chcesz przenieść IDOK pionie. Możesz także grupować je, ale robi się to trudne (czasami nie rozumiem, co się dzieje) ... ale gdy już to zrobisz, nie jest tak źle. :)


Oto samowystarczalny przykład:

#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(); 
} 

go skompilować, należy również plik o nazwie resource.h z następujących zawartości w tym samym folderze projektu:

#define IDD_DIALOG1      101 
#define IDR_RT_MANIFEST1    103 

Plik o nazwie Sample.rc został dodany do projektu, który można edytować za pomocą programu Visual Studio i który zawiera układ okna dialogowego:

#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 
+1

@NathanMcCrina: ATL jest dosłownie tylko interfejsem C++ dla Win32 - jeśli używasz C++, po prostu będziesz miał problemy z używaniem interfejsów API w stylu C - dodaje * nic * i sprawia, że ​​kierujesz się złymi praktykami (np. wiele zmiennych globalnych, które są złym pomysłem, ale łatwym błędem). Jeśli chodzi o DirectX: jestem prawie pewny, że pasują do siebie dobrze - w końcu nie różni się to od Win32, ponieważ jest to to samo. Czy pełny przykład pomocy ATL (prawdopodobnie nie ma DirectX, jak wyświetlić okno dialogowe)? Mogę zrobić dialog i pokazać, jak to naprawdę nie jest takie trudne. – Mehrdad

+0

Jasne, nie będę odmawiać przykładów! –

+0

@NathanMcCrina: Zobacz aktualizację. – Mehrdad

3

Here i here można znaleźć kilka sprawdzonych przykładów, jak to zrobić. Nie trzeba wymyślać koła.