UI的正确设计模式是什么?

时间:2014-09-23 13:13:46

标签: winapi visual-c++

我正在制作一个小应用程序,用于从外部设备加载数据。它使用DLL。

我想让应用在一个窗口中运行。通过菜单,应该可以调出正确的UI状态。我不想使用对话框或单独的窗口。

我的想法是使用状态变量并让WM_PAINT消息处理窗口的不同内容(createwindowEx用于不同的文本和按钮项目,即。)。

这是正确的方法吗?我搜索过互联网,阅读编程Windows并搜索了stackoverflow,但找不到一个简单的例子。它始终使用具有专用winproc功能的不同窗口。感觉我不需要......

有人可以帮我指点方向或小例子吗?

THX

编辑: 我附上我到目前为止的代码。有人可以看看,Thx。

#if defined _MSC_VER || defined __BORLANDC__
#define OEMRESOURCE
#endif

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

#include <windows.h>  //include all the basics
#include <tchar.h>    //string and other mapping macros
#include <iostream>
#include <string>
#include "hrmcom.h"
#include "resource.h"

typedef std::basic_string<TCHAR> ustring;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildProc(HWND, UINT, WPARAM, LPARAM);

inline int ErrMsg(const ustring&);
bool CreateChild(HWND);
bool CreateChildScreen(HWND);

ustring classname = TEXT("MAINWND");
ustring childname = TEXT("CHILDWND");

HWND    hwndChild[3], hwndCtrl[CTRNUM];

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR pStr, int nCmd)
{
WNDCLASSEX wcx = { 0 };  

wcx.cbSize = sizeof(WNDCLASSEX);
wcx.lpfnWndProc = WndProc;             
wcx.hInstance = hInst;   
wcx.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON1));
wcx.hCursor = reinterpret_cast<HCURSOR>(LoadImage(0, IDC_ARROW,
    IMAGE_CURSOR, 0, 0, LR_SHARED));
wcx.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BTNFACE + 1);
wcx.lpszClassName = classname.c_str();

if (!RegisterClassEx(&wcx))
{
    ErrMsg(_T("Failed to register wnd class"));
    return -1;
}
wcx.lpfnWndProc = ChildProc;
wcx.cbWndExtra = sizeof (long);
wcx.hIcon = NULL;
wcx.lpszClassName = childname.c_str();

if (!RegisterClassEx(&wcx))
{
    ErrMsg(_T("Failed to register wnd class"));
    return -1;
}

HMENU hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU));

HWND hwnd = CreateWindowEx(0,                     
    classname.c_str(),       
    TEXT("Polar Loader"),      
    WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,     
    400, 200, 600, 300,       
    0,                     
    hMenu,                   
    hInst,                  
    0);                      
if (!hwnd)
{
    ErrMsg(TEXT("Failed to create wnd"));
    return -1;
}

ShowWindow(hwnd, nCmd);
UpdateWindow(hwnd);

MSG msg;
while (GetMessage(&msg, 0, 0, 0)>0)
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
 }

 LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
switch (uMsg)
{
case WM_CREATE:
    //Create the Childwindows
    if (!CreateChild(hwnd))
    {
        ErrMsg(TEXT("Failed to create Childwindows"));
        return -1;
    }
    //Create controls of the Childwindows 
    if (!CreateChildScreen(hwnd))
    {
        ErrMsg(TEXT("Failed to create Conrols of Childwindows"));
        return -1;
    }
    return 0;
  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case IDM_Acc:
        ShowWindow(hwndChild[0], SW_SHOW);
        return 0;
    case IDM_Con:
    case IDM_Help:
    case IDM_Log:
    case IDM_Pol:
    case IDM_Trans:
        ShowWindow(hwndChild[0], SW_HIDE);
        return 0;       
    }

case WM_DESTROY:
    PostQuitMessage(0);    //signal end of application
    return 0;
default:
    //let system deal with msg
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
 }
 LRESULT CALLBACK ChildProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
switch (uMsg)
{   
case WM_CREATE:
    SetWindowLong(hwnd, 0, 0);      
    return 0;
case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case ID_CTRL+5:         
        MessageBeep(0);
        return 0;
    }
default:
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
 }


 inline int ErrMsg(const ustring& s)
 {
return MessageBox(0, s.c_str(), _T("ERROR"), MB_OK | MB_ICONEXCLAMATION);
 }


 bool CreateChild(HWND hwnd)
 {
static int x;
for (x = 0; x < 3; x++)
{
    hwndChild[x] = CreateWindowEx(0, childname.c_str(), NULL,
        WS_CHILDWINDOW,
        0, 0, 600, 300,
        hwnd, (HMENU)x,
        (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
        NULL);
    if (!hwndChild[x]) return FALSE;
}
return TRUE;
 }

 bool CreateChildScreen(HWND hwnd)
 {
LPCWSTR lpType[CTRNUM] = { TEXT("static"), TEXT("edit"), TEXT("edit"), TEXT("static"), TEXT("static"), TEXT("button") };
LPCWSTR lpName[CTRNUM] = { TEXT("Log on to Gedysan Training App:"), TEXT(""), TEXT(""), TEXT("Username:"), TEXT("Password:"), TEXT("Log on") };
DWORD dStyle[CTRNUM] = { WS_CHILD | WS_VISIBLE | ES_LEFT,
    WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER | ES_AUTOHSCROLL,
    WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER | ES_PASSWORD | ES_AUTOHSCROLL,
    WS_CHILD | WS_VISIBLE | ES_LEFT,
    WS_CHILD | WS_VISIBLE | ES_LEFT,
    WS_CHILD | WS_VISIBLE | ES_LEFT
};
RECT rc[CTRNUM] = { { 15, 10, 400, 25 }, { 100, 40, 150, 25 }, { 100, 70, 150, 25 }, { 15, 45, 70, 25 }, { 15, 75, 70, 25 }, { 15, 110, 70, 25 } };
int iChildNum[CTRNUM] = { 0, 0, 0, 0, 0, 0 };
static int x;
for (x = 0; x < CTRNUM; x++)
{
    RECT x1 = rc[x];
    hwndCtrl[x] = CreateWindowEx(0, lpType[x], lpName[x], dStyle[x],
        x1.left, x1.top, x1.right, x1.bottom,
        hwndChild[iChildNum[0]], (HMENU)(ID_CTRL + x),
        (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE), 0);
    if (!hwndChild[x]) return FALSE;
}
return TRUE;
 }

1 个答案:

答案 0 :(得分:2)

使用您提出的方法,您将在WM_PAINT处理程序中获得大量无关的内容,从而使设计变得混乱。选择菜单后,您会收到一条消息。在该消息处理程序中运行与该菜单命令相关的代码。

如果您的UI由控件组成,那么WM_PAINT根本不涉及:这些控件会自己绘制。你的WM_PAINT处理程序应该做你需要的任何自定义绘画,没有别的。