MSDN.WhiteKnight - Stack Overflow answers
Ответ на "C++ WinApi отделить UI View от кода"
Answer 885206
На самом деле можно, это называется Ресурсы диалоговых окон. Несмотря на название, их область использования куда шире, чем диалоговые окна в традиционном смысле. Например, ничто не мешает:
Сделать главное окно приложение диалоговым, если оно состоит исключительно из элементов управления и не содержит сложной логики отрисовки.
Создать диалоговое окно со стилем WS_CHILD и вкладывать его в другие окна (аналог User Control).
Пример. Нарисуем с помощью редактора ресурсов Visual Studio такое диалоговое окно:
Редактор ресурсов не содержится в студии Express-версий, поэтому при их использовании нужно будет найти сторонний редактор или редактировать определения ресурсов вручную (см. ниже).
В результате получим файл ресурсов и заголовочный файл. Откроем их в текстовом редакторе и удалим лишний текст, сгенерированный IDE, получим в результате:
Resource.h (идентификаторы элементов управления, используются для связи кода с UI)
#define IDD_CALC 103 #define IDC_INPUT1 1000 #define IDC_INPUT2 1001 #define IDC_PLUS 1002 #define IDC_MINUS 1003 #define IDC_MULTI 1004 #define IDC_DIV 1005
Resource.rc (определение UI, аналог XAML)
#include "resource.h" #include "windows.h" LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_CALC DIALOGEX 0, 0, 217, 89 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Супер калькулятор" FONT 8, "MS Shell Dlg", 0, 0, 0x1 BEGIN DEFPUSHBUTTON "Выход",IDOK,160,68,50,14,WS_GROUP EDITTEXT IDC_INPUT1,15,14,47,15,ES_AUTOHSCROLL | ES_NUMBER EDITTEXT IDC_INPUT2,15,36,47,15,ES_AUTOHSCROLL | ES_NUMBER PUSHBUTTON "+",IDC_PLUS,77,15,18,12 PUSHBUTTON "-",IDC_MINUS,105,15,18,12 PUSHBUTTON "*",IDC_MULTI,77,36,18,12 PUSHBUTTON "/",IDC_DIV,105,36,18,12 END
Далее добавим код:
Model.cpp
#include <windows.h> #include "resource.h" //Логика вычислений BOOL Calculate(UINT idAction, int arg1, int arg2, int* pOutput) { if (pOutput == NULL) return FALSE; if (idAction == IDC_DIV && arg2 == 0) return FALSE; switch (idAction) { case IDC_PLUS: *pOutput = arg1 + arg2; return TRUE; case IDC_MINUS: *pOutput = arg1 - arg2; return TRUE; case IDC_MULTI: *pOutput = arg1 * arg2; return TRUE; case IDC_DIV: *pOutput = arg1 / arg2; return TRUE; } return FALSE; }
ViewModel.cpp
#include <windows.h> #include <stdlib.h> #include <tchar.h> #include "resource.h" //объявления функций BOOL InitInstance(HINSTANCE, int); INT_PTR CALLBACK DlgCalc_Callback(HWND, UINT, WPARAM, LPARAM); BOOL Calculate(UINT idAction, int arg1, int arg2, int* pOutput); // Глобальные переменные HINSTANCE hInst; HWND hWnd = NULL; // Точка входа int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // Выполнить инициализацию приложения if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } MSG msg; // Цикл основного сообщения while (GetMessage(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } //Инициализация приложения BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; //создать окно CreateDialog(hInstance, MAKEINTRESOURCE(IDD_CALC), NULL, DlgCalc_Callback); if (!hWnd) { return FALSE; } //отобразить окно ShowWindow(hWnd, nCmdShow); return TRUE; } //Логика обработки команд в окне INT_PTR ProcessCommand(HWND hDlg, UINT idAction) { BOOL success = FALSE; int x, y, res; if (idAction == IDOK || idAction == IDCANCEL) { //закрыть окно DestroyWindow(hDlg); return (INT_PTR)TRUE; } if (idAction >= IDC_PLUS && idAction <= IDC_DIV) { //получение входных данных x = GetDlgItemInt(hDlg, IDC_INPUT1, &success, TRUE); if (success == FALSE) { MessageBox(hDlg, L"Введенное число некорректно", NULL, MB_OK | MB_ICONERROR); return (INT_PTR)TRUE; } y = GetDlgItemInt(hDlg, IDC_INPUT2, &success, TRUE); if (success == FALSE) { MessageBox(hDlg, L"Введенное число некорректно", NULL, MB_OK | MB_ICONERROR); return (INT_PTR)TRUE; } //выполнение команды success = Calculate(idAction, x, y, &res); if (success == FALSE) { MessageBox(hDlg, L"При вычислении произошла ошибка", NULL, MB_OK | MB_ICONERROR); return (INT_PTR)TRUE; } //вывод результата SetDlgItemText(hDlg, IDC_INPUT2, L""); SetDlgItemInt(hDlg, IDC_INPUT1, res, TRUE); return (INT_PTR)TRUE; } return (INT_PTR)FALSE; } INT_PTR CALLBACK DlgCalc_Callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); UINT idAction; switch (message) { case WM_INITDIALOG: hWnd = hDlg; return (INT_PTR)TRUE; case WM_COMMAND: idAction = LOWORD(wParam); return ProcessCommand(hDlg, idAction); case WM_DESTROY: PostQuitMessage(0); break; } return (INT_PTR)FALSE; }
В итоге получаем приложение с разделением на декларативное определение UI, логику UI и логику вычислений, хотя по возможностям это и далеко от WPF/XAML.
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.