不用资源文件的 VC 窗口程序
1.单个文件的windows VC程序,不用资源文件。在win32模板程序基础上改。
2. 菜单 和 热键 的代码添加
3. 模式对话框的代码添加。
程序运行界面,最简的win32程序
代码如下,单个文件,比较麻烦的就是对话框。
2023-7-10 修改: 模式对话框之前用MSDN中直接写内存的例子创建控件,比较难控制。
可以只创建一个空窗口,然后在InitDialog 中用通常窗口中创建控件的方法。比较方便直观。
LRESULT InputBox2(HINSTANCE hinst, HWND hwndOwner, LPTSTR lpszMessage, void* p) { LRESULT ret; int nchar; HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPWORD lpw; hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024); lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); lpdt = (LPDLGTEMPLATE)hgbl; lpdt->style = WS_POPUP | WS_BORDER | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU; //DS_MODALFRAME lpdt->cdit = 0; // number of controls lpdt->x = 100; lpdt->y = 50; lpdt->cx = 200; lpdt->cy = 150; lpw = (LPWORD)(lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) wcscpy((wchar_t*)lpw, L"DialogBoxIndirect"); nchar = wcslen((wchar_t*)lpw) + 1; lpw += nchar; GlobalUnlock(hgbl); ret = DialogBoxIndirectParam(hinst, (LPDLGTEMPLATE)hgbl, hwndOwner, (DLGPROC)DlgProc, (LPARAM)p); GlobalFree(hgbl); return ret; } #define IDC_EDIT1 1000 #define IDC_BNOK 1001 #define IDC_BNCANCEL 1002 // Mesage handler for about box. LRESULT CALLBACK DlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { wchar_t str[100]; static void* p; static HWND hWndEdit1; static HWND hWndBNOK; static HWND hWndBNCANCEL; switch (message) { case WM_INITDIALOG: hWndEdit1 = CreateWindow(_T("edit"), NULL, WS_CHILD | WS_BORDER | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL,// | ES_READONLY 10, 10, 180, 50, hWnd, (HMENU)IDC_EDIT1, hInst, NULL); hWndBNOK = CreateWindow(_T("button"), _T("OK"), WS_CHILD | WS_VISIBLE | BS_FLAT, 40, 100, 50, 30, hWnd, (HMENU)IDOK, hInst, NULL); hWndBNCANCEL = CreateWindow(_T("button"), _T("CANCEL"), WS_CHILD | WS_VISIBLE | BS_FLAT, 100, 100, 50, 30, hWnd, (HMENU)IDCANCEL, hInst, NULL); //参数只能在INITDIALOG消息中传进,但是没接口传出,先用个静态变量保存指针 wcscpy(str, (wchar_t*)lParam); SetDlgItemText(hWnd, IDC_EDIT1, str); p = (void*)lParam; return TRUE; case WM_SIZE: int cxClient, cyClient; cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); MoveWindow(hWndEdit1, 10, 10, 180, 50, TRUE); MoveWindow(hWndBNOK, 40, 100, 50, 30, TRUE); MoveWindow(hWndBNCANCEL, 100, 100, 50, 30, TRUE); break; case WM_PAINT: break; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { GetDlgItemText(hWnd, IDC_EDIT1, str, 100); str[99] = 0; wcscpy((wchar_t*)p, str); EndDialog(hWnd, LOWORD(wParam)); return TRUE; } break; } return FALSE; }
下面是之前仿MSDN直接写内存创建控件的完整测试程序
// NOT.cpp : // //#include "stdafx.h" #include <windows.h> #include <stdlib.h> #include <malloc.h> #include <memory.h> #include <tchar.h> //#include "resource.h" #define IDR_MAINFRAME 128 #define IDD_NOT_DIALOG 102 #define IDD_ABOUTBOX 103 #define IDC_NOT 109 #define IDC_STATIC -1 #define IDM_FILE_NEW 20001 #define IDM_FILE_EXIT 20002 #define IDM_TEST_TEST1 20011 #define IDM_TEST_TEST2 20012 #define IDM_HELP 20021 #define IDM_ABOUT 20022 #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING] = _T("NOT"); // The title bar text TCHAR szWindowClass[MAX_LOADSTRING] = _T("NOT_XGZ_2023"); // The title bar text //xgz HMENU m_hMenu = NULL; HMENU m_hMenuPopup = NULL; int InitMenu(); int OnCreate(HWND, UINT, WPARAM, LPARAM); int OnPaint(HWND, UINT, WPARAM, LPARAM); int OnRButtonUp(HWND, UINT, WPARAM, LPARAM); int OnTest1(HWND, UINT, WPARAM, LPARAM); HACCEL InitAccel(); // Foward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; HACCEL hAccelTable; MyRegisterClass(hInstance); if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } //hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_NOT); //WM_SYSCOMMAND hAccelTable = InitAccel(); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION); //标准图标 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION); //标准图标 return RegisterClassEx(&wcex); } int InitMenu() { HMENU hMenu,hMenuPopup; hMenu = CreateMenu(); m_hMenu = hMenu; //主菜单 hMenuPopup = CreateMenu(); AppendMenu(hMenuPopup, MF_STRING, IDM_FILE_NEW, _T("&New")); AppendMenu(hMenuPopup, MF_SEPARATOR, 0, NULL); AppendMenu(hMenuPopup, MF_STRING, IDM_FILE_EXIT, _T("&Exit")); AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hMenuPopup, _T("&File")); //File hMenuPopup = CreateMenu(); m_hMenuPopup = hMenuPopup; //选一个做主程序的右键弹出菜单 AppendMenu(hMenuPopup, MF_STRING, IDM_TEST_TEST1, _T("&Test1")); AppendMenu(hMenuPopup, MF_STRING, IDM_TEST_TEST2, _T("&Test2")); AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hMenuPopup, _T("&Test")); //Test AppendMenu(hMenu, MF_STRING, IDM_HELP, _T("&Help")); AppendMenu(hMenu, MF_STRING, IDM_ABOUT, _T("&About")); return 0; } HACCEL InitAccel() { ACCEL AccelTable[3] = { {FVIRTKEY | FCONTROL, VK_UP, IDM_TEST_TEST1}, {FVIRTKEY | FALT, VK_F2, IDM_TEST_TEST2}, 0 }; HACCEL hAccel = CreateAcceleratorTable(AccelTable, 2); return hAccel; } BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } InitMenu(); SetMenu(hWnd, m_hMenu); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } #define ID_HELP 150 #define ID_TEXT 200 #define ID_EDIT 1200 LPWORD lpwAlign(LPWORD lpIn) { ULONG ul; ul = (ULONG)lpIn; ul += 3; ul >>= 2; ul <<= 2; return (LPWORD)ul; } LRESULT InputBox(HINSTANCE hinst, HWND hwndOwner, LPTSTR lpszMessage, void* p) { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; LRESULT ret; int nchar; hgbl = GlobalAlloc(GMEM_ZEROINIT, 2024); if (!hgbl) return -1; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); //=====窗体============. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION; lpdt->cdit = 4; // number of controls lpdt->x = 100; lpdt->y = 50; lpdt->cx = 200; lpdt->cy = 150; lpw = (LPWORD)(lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) wcscpy((wchar_t*)lpw, L"DialogBoxIndirect"); nchar = wcslen((wchar_t*)lpw) + 1; lpw += nchar; //=======static text ============= lpw = lpwAlign(lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 10; lpdit->y = 10; lpdit->cx = 180; lpdit->cy = 20; lpdit->id = ID_TEXT; // text identifier lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0082; // static class lpwsz = (LPWSTR)lpw; wcscpy((wchar_t*)lpw, lpszMessage); //初始化字符串 nchar = wcslen((wchar_t*)lpw) + 1; lpw += nchar; lpw = lpwAlign(lpw); // align creation data on DWORD boundary *lpw++ = 0; // no creation data //====== Edit ================= lpw = lpwAlign(lpw); lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 10; lpdit->y = 40; lpdit->cx = 180; lpdit->cy = 50; lpdit->id = ID_EDIT; // edit identifier lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_BORDER | ES_MULTILINE | WS_VSCROLL; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0081; // Edit class lpwsz = (LPWSTR)lpw; wcscpy((wchar_t*)lpw, L"Input"); //初始化字符串 nchar = wcslen((wchar_t*)lpw); //XGZ 这里不能 +1,末尾的0被去掉了??? lpw += nchar; lpw = lpwAlign(lpw); *lpw++ = 0; //========= OK button.============== lpw = lpwAlign(lpw); lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 80; lpdit->y = 120; lpdit->cx = 40; lpdit->cy = 20; lpdit->id = IDOK; // OK button identifier lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR)lpw; wcscpy((wchar_t*)lpw, L"OK"); nchar = wcslen((wchar_t*)lpw) + 1; lpw += nchar; lpw = lpwAlign(lpw); // align creation data on DWORD boundary *lpw++ = 0; // no creation data //======CANCEL button.========= lpw = lpwAlign(lpw); lpdit = (LPDLGITEMTEMPLATE)lpw; lpdit->x = 140; lpdit->y = 120; lpdit->cx = 40; lpdit->cy = 20; lpdit->id = IDCANCEL; // CANCEL button identifier lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON; lpw = (LPWORD)(lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR)lpw; wcscpy((wchar_t*)lpw, L"CANCEL"); nchar = wcslen((wchar_t*)lpw) + 1; lpw += nchar; lpw = lpwAlign(lpw); *lpw++ = 0; GlobalUnlock(hgbl); //ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE)hgbl,hwndOwner, (DLGPROC)About); //用带参数的方便扩展 ret = DialogBoxIndirectParam(hinst, (LPDLGTEMPLATE)hgbl,hwndOwner, (DLGPROC)About, (LPARAM)p); GlobalFree(hgbl); return ret; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; wchar_t p[100] = _T("This is a test"); switch (message) { case WM_CREATE: OnCreate(hWnd, message, wParam, lParam); break; case WM_PAINT: OnPaint(hWnd, message, wParam, lParam); break; case WM_RBUTTONUP: OnRButtonUp(hWnd, message, wParam, lParam); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_TEST_TEST1: OnTest1(hWnd, message, wParam, lParam); break; case IDM_HELP: break; case IDM_ABOUT: //DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); InputBox(hInst, hWnd, _T("This is a DialogBoxIndirectParam sample."), (void*)p); MessageBox(NULL, p, _T("Input"), MB_OK); break; case IDM_FILE_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } int OnCreate(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return 0; } int OnPaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... RECT rt; GetClientRect(hWnd, &rt); DrawText(hdc, _T("NOT"), lstrlen(_T("NOT")), &rt, DT_CENTER); EndPaint(hWnd, &ps); return 0; } int OnRButtonUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { POINT point; //point.x = LOWORD(lParam); //point.y = LOWORD(lParam); //ClientToScreen(hWnd, &point); //xgz 位置不对 ??? GetCursorPos(&point); //xgz 直接取屏幕坐标 TrackPopupMenu(m_hMenuPopup, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL); return 0; } int OnTest1(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc = GetDC(hWnd); TCHAR* p = _T("Test1"); TextOut(hdc, 10, 10, p, lstrlen(p)); ReleaseDC(hWnd, hdc); return 0; } // Mesage handler for about box. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { HWND hWndEdit; wchar_t str[100]; static void* p; switch (message) { case WM_INITDIALOG: //参数只能在INITDIALOG消息中传进,但是没接口传出,先用个静态变量保存指针 wcscpy(str, (wchar_t*) lParam); SetDlgItemText(hDlg, ID_EDIT, str); p = (void*)lParam; return TRUE; case WM_PAINT: break; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { hWndEdit = GetDlgItem(hDlg, ID_EDIT); GetDlgItemText(hDlg, ID_EDIT, str, 100); str[99] = 0; wcscpy((wchar_t*)p, str); EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; }