#include <windows.h> #include <commctrl.h> #include <vector> #include <string> #include <iostream> #pragma comment(lib, "comctl32.lib") #pragma comment(lib, "riched20.lib") // 控件 ID #define ID_PANEL_TOP 100 #define ID_SPLITTER 101 #define ID_PANEL_BOTTOM 102 #define ID_BTN1 200 #define ID_BTN2 201 #define ID_BTN3 202 #define ID_RICHEDIT 300 #define ID_STATUSBAR 400 #define ID_TIMER 500 using namespace std; LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void OnDragDrop(HWND hwnd, WPARAM wParam, LPARAM lParam); void AddLogEntry(const std::string& entry); // 全局變數,讓 hRichTextBox 在所有函數中可見 HWND hRichTextBox; HWND hButton1; HWND hButton2; HWND hButton3; int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) { // 初始化公共控件 InitCommonControls(); // 設置窗口類 const char CLASS_NAME[] = "Sample Window Class"; WNDCLASS wc = {}; wc.lpfnWndProc = WindowProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME; RegisterClass(&wc); // 創建窗口 HWND hwnd = CreateWindowEx(0, CLASS_NAME, "Dev-C++ Example", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // 添加日誌條目 AddLogEntry("Hello 2"); AddLogEntry("Hello 3"); // Reference: https://stackoverflow.com/questions/1333527/how-do-i-print-to-the-debug-output-window-in-a-win32-app // OutputDebugString("Start."); // 主消息循環 MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HWND hPanel1, hPanel2, hStatusBar; static int panel1Height = 240; // Panel1 的高度 static int _PrevMsgNumber = 0; char buf[32]; switch (uMsg) { case WM_LBUTTONDOWN: // Mouse left button pressed down AddLogEntry("Mouse Left Button Down"); return 0; case WM_CREATE: { HINSTANCE hInst = ((LPCREATESTRUCT)lParam)->hInstance; // for instance // 創建 Panel1 hPanel1 = CreateWindowEx(0, "STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 800, panel1Height, hwnd, NULL, NULL, NULL); // 創建三個按鈕 CreateWindow("BUTTON", "Button 1", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 10, 100, 25, hwnd, (HMENU)ID_BTN1, ((LPCREATESTRUCT) lParam)->hInstance, NULL); CreateWindow("BUTTON", "Button 2", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 50, 100, 25, hwnd, (HMENU)ID_BTN2, ((LPCREATESTRUCT) lParam)->hInstance, NULL); CreateWindow("BUTTON", "Button 3", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 90, 100, 25, hwnd, (HMENU)ID_BTN3, ((LPCREATESTRUCT) lParam)->hInstance, NULL); // 創建 Panel2 hPanel2 = CreateWindowEx(0, "STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 0, panel1Height, 800, 360, hwnd, NULL, NULL, NULL); // 創建 RichTextBox,使用全局變數 hRichTextBox hRichTextBox = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL, 0, 0, 800, 360, hPanel2, NULL, NULL, NULL); // 啟用拖放 DragAcceptFiles(hwnd, TRUE); // 創建狀態欄 // hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE, "Status Bar", hwnd, 0); hStatusBar = CreateWindowA( STATUSCLASSNAMEA, NULL, WS_CHILD | WS_VISIBLE, 0,0,0,0, hwnd, (HMENU)ID_STATUSBAR, hInst, NULL); SendMessage(hStatusBar, WM_SIZE, 0, 0); // 啟動 1 秒定時器 SetTimer(hwnd, ID_TIMER, 1000, NULL); } return 0; case WM_SIZE: { // 調整 Panel1 和 Panel2 大小 MoveWindow(hPanel1, 0, 0, LOWORD(lParam), panel1Height, TRUE); MoveWindow(hPanel2, 0, panel1Height, LOWORD(lParam), HIWORD(lParam) - panel1Height, TRUE); // 要減掉狀態欄的高度為 20 MoveWindow(hRichTextBox, 0, 0, LOWORD(lParam), HIWORD(lParam) - panel1Height - 20, TRUE); MoveWindow(hStatusBar, 0, HIWORD(lParam) - 20, LOWORD(lParam), 20, TRUE); // 假設狀態欄的高度為 20 } return 0; case WM_DROPFILES: { wsprintfA(buf, "Drop File %d",uMsg); AddLogEntry(buf); OnDragDrop(hwnd, wParam, lParam); } return 0; case WM_COMMAND: //case WA_CLICKACTIVE: { // AddLogEntry("WM_COMMAND Pressed"); // 處理各控件的 _click() 事件 wsprintfA(buf, "Message %d",uMsg); AddLogEntry(buf); switch (LOWORD(wParam)) { case ID_BTN1: //wsprintfA(buf, "Bbtton 1"); //SendMessageA(hStatusBar, SB_SETTEXTA, 0 | SBT_NOBORDERS, (LPARAM)buf); AddLogEntry("Button 1 Pressed"); break; case ID_BTN2: AddLogEntry("Button 2 Pressed"); break; case ID_BTN3: AddLogEntry("Button 3 Pressed"); // OutputDebugString("My output string."); break; } return 0; } case WM_TIMER: { // 處理計時器事件 if (wParam == ID_TIMER) { SYSTEMTIME st; GetLocalTime(&st); char buf[32]; wsprintfA(buf, "%04d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); SendMessageA(hStatusBar, SB_SETTEXTA, 0 | SBT_NOBORDERS, (LPARAM)buf); // AddLogEntry (buf); } return 0; } case WM_DESTROY: KillTimer(hwnd, ID_TIMER); // 刪除Timer PostQuitMessage(0); return 0; } //case WM_GETHOTKEY: //{ // return 0; //} //if (_PrevMsgNumber != uMsg) //{ // _PrevMsgNumber = uMsg; // wsprintfA(buf, "Message %d",_PrevMsgNumber); // AddLogEntry(buf); //} return DefWindowProc(hwnd, uMsg, wParam, lParam); } void OnDragDrop(HWND hwnd, WPARAM wParam, LPARAM lParam) { HDROP hDrop = (HDROP)wParam; UINT cnt = DragQueryFileA(hDrop, 0xFFFFFFFF, NULL, 0); AddLogEntry("On Drag Drop"); for (UINT i = 0; i < cnt; i++) { char path[MAX_PATH]; DragQueryFileA(hDrop, i, path, MAX_PATH); // 手动判断扩展名 char *ext = strrchr(path, '.'); if (ext && _stricmp(ext, ".config") == 0) { //AddLogEntry(path); } AddLogEntry(std::to_string(i)); // 將文件名添加到日誌 //AddLogEntry(fileName); } DragFinish(hDrop); } void AddLogEntry(const std::string& entry) { std::cout << "Log Entry: " << entry << std::endl; // 調試輸出 int len = GetWindowTextLength(hRichTextBox); SendMessage(hRichTextBox, EM_SETSEL, len, len); SendMessage(hRichTextBox, EM_REPLACESEL, TRUE, (LPARAM)entry.c_str()); SendMessage(hRichTextBox, EM_REPLACESEL, TRUE, (LPARAM)"\r\n"); }
// SplitterANSI.cpp #include <windows.h> #include <commctrl.h> #include <richedit.h> #include <shellapi.h> #include <stdio.h> #include <string.h> // 控件 ID #define ID_PANEL_TOP 100 #define ID_SPLITTER 101 #define ID_PANEL_BOTTOM 102 #define ID_BTN1 200 #define ID_BTN2 201 #define ID_BTN3 202 #define ID_RICHEDIT 300 #define ID_STATUSBAR 400 #define ID_TIMER 500 // 全局句柄 HWND hPanelTop, hSplitter, hPanelBot, hBtn1, hBtn2, hBtn3, hRE, hStatus; bool dragging = false; LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_CREATE: { HINSTANCE hInst = ((LPCREATESTRUCT)lParam)->hInstance; // 上半区 Panel1 hPanelTop = CreateWindowA( "STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_ETCHEDFRAME, 0,0,0,0, hWnd, (HMENU)ID_PANEL_TOP, hInst, NULL); // Splitter(高 4 像素) hSplitter = CreateWindowA( "STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_ETCHEDFRAME, 0,0,0,4, hWnd, (HMENU)ID_SPLITTER, hInst, NULL); // 下半区 Panel2 hPanelBot = CreateWindowA( "STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_ETCHEDFRAME, 0,0,0,0, hWnd, (HMENU)ID_PANEL_BOTTOM, hInst, NULL); // 三个按钮 hBtn1 = CreateWindowA("BUTTON", "Button 1", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0,0,0,0, hPanelTop, (HMENU)ID_BTN1, hInst, NULL); hBtn2 = CreateWindowA("BUTTON", "Button 2", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0,0,0,0, hPanelTop, (HMENU)ID_BTN2, hInst, NULL); hBtn3 = CreateWindowA("BUTTON", "Button 3", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 0,0,0,0, hPanelTop, (HMENU)ID_BTN3, hInst, NULL); // RichEdit 下半区 LoadLibraryA("Msftedit.dll"); hRE = CreateWindowExA( 0, "RICHEDIT50W", "Hello\n", WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN, 0,0,0,0, hPanelBot, (HMENU)ID_RICHEDIT, hInst, NULL); // StatusBar hStatus = CreateWindowA( STATUSCLASSNAMEA, NULL, WS_CHILD | WS_VISIBLE, 0,0,0,0, hWnd, (HMENU)ID_STATUSBAR, hInst, NULL); // 接受文件拖放 DragAcceptFiles(hPanelTop, TRUE); // 启动 1 秒定时器 SetTimer(hWnd, ID_TIMER, 1000, NULL); } return 0; case WM_SIZE: { // 计算尺寸 RECT rc; GetClientRect(hWnd, &rc); // StatusBar 调整大小 SendMessageA(hStatus, WM_SIZE, 0, 0); RECT rcSB; SendMessageA(hStatus, SB_GETRECT, 0, (LPARAM)&rcSB); int sbH = rcSB.bottom - rcSB.top; int availH = rc.bottom - sbH; int topH = (int)(availH * 0.4); const int spH = 4; // 布局 MoveWindow(hPanelTop, 0, 0, rc.right, topH, TRUE); MoveWindow(hSplitter, 0, topH, rc.right, spH, TRUE); MoveWindow(hPanelBot, 0, topH+spH, rc.right, availH-topH-spH, TRUE); // 按钮等分 int btnH = topH / 3; MoveWindow(hBtn1, 0, 0, rc.right, btnH, TRUE); MoveWindow(hBtn2, 0, btnH, rc.right, btnH, TRUE); MoveWindow(hBtn3, 0, btnH*2, rc.right, topH-btnH*2, TRUE); // RichEdit 填满 PanelBot MoveWindow(hRE, 0, 0, rc.right, availH-topH-spH, TRUE); } return 0; case WM_LBUTTONDOWN: { POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; RECT r; GetWindowRect(hSplitter, &r); ScreenToClient(hWnd, (LPPOINT)&r); if (pt.y >= r.top && pt.y <= r.bottom) { dragging = true; SetCapture(hWnd); } } return 0; case WM_MOUSEMOVE: if (dragging) { int y = GET_Y_LPARAM(lParam); RECT rc; GetClientRect(hWnd, &rc); RECT rcSB; SendMessageA(hStatus, SB_GETRECT, 0, (LPARAM)&rcSB); int sbH = rcSB.bottom - rcSB.top; int availH = rc.bottom - sbH; if (y < 0) y = 0; if (y > availH) y = availH; const int spH = 4; MoveWindow(hPanelTop, 0,0,rc.right,y, TRUE); MoveWindow(hSplitter, 0,y,rc.right,spH, TRUE); MoveWindow(hPanelBot, 0,y+spH, rc.right, availH-y-spH, TRUE); int btnH = y / 3; MoveWindow(hBtn1, 0, 0, rc.right, btnH, TRUE); MoveWindow(hBtn2, 0, btnH, rc.right, btnH, TRUE); MoveWindow(hBtn3, 0, btnH*2, rc.right, y-btnH*2, TRUE); MoveWindow(hRE, 0, 0, rc.right, availH-y-spH, TRUE); } return 0; case WM_LBUTTONUP: if (dragging) { dragging = false; ReleaseCapture(); } return 0; case WM_DROPFILES: { HDROP hDrop = (HDROP)wParam; UINT cnt = DragQueryFileA(hDrop, 0xFFFFFFFF, NULL, 0); for (UINT i = 0; i < cnt; i++) { char path[MAX_PATH]; DragQueryFileA(hDrop, i, path, MAX_PATH); // 手动判断扩展名 char *ext = strrchr(path, '.'); if (ext && _stricmp(ext, ".config") == 0) { int len = GetWindowTextLengthA(hRE); SendMessageA(hRE, EM_SETSEL, len, len); SendMessageA(hRE, EM_REPLACESEL, 0, (LPARAM)path); SendMessageA(hRE, EM_REPLACESEL, 0, (LPARAM)"\r\n"); } } DragFinish(hDrop); } return 0; case WM_COMMAND: { int id = LOWORD(wParam); const char* msg = NULL; if (id == ID_BTN1) msg = "Button 1 Pressed\r\n"; if (id == ID_BTN2) msg = "Button 2 Pressed\r\n"; if (id == ID_BTN3) msg = "Button 3 Pressed\r\n"; if (msg) { int len = GetWindowTextLengthA(hRE); SendMessageA(hRE, EM_SETSEL, len, len); SendMessageA(hRE, EM_REPLACESEL, 0, (LPARAM)msg); } } return 0; case WM_TIMER: if (wParam == ID_TIMER) { SYSTEMTIME st; GetLocalTime(&st); char buf[32]; wsprintfA(buf, "%04d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); SendMessageA(hStatus, SB_SETTEXTA, 0 | SBT_NOBORDERS, (LPARAM)buf); } return 0; case WM_DESTROY: KillTimer(hWnd, ID_TIMER); PostQuitMessage(0); return 0; } return DefWindowProcA(hWnd, msg, wParam, lParam); } int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow) { INITCOMMONCONTROLSEX icc = { sizeof(icc), ICC_BAR_CLASSES }; InitCommonControlsEx(&icc); WNDCLASSA wc = {0}; wc.lpfnWndProc = WndProc; wc.hInstance = hInst; wc.lpszClassName = "SplitWinANSI"; wc.hCursor = LoadCursorA(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); RegisterClassA(&wc); HWND hWnd = CreateWindowA( wc.lpszClassName, "Win32 SplitContainer Demo (ANSI)", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInst, NULL); ShowWindow(hWnd, nCmdShow); MSG msg; while (GetMessageA(&msg, NULL, 0, 0)) DispatchMessageA(&msg); return (int)msg.wParam; }