/////////////////////////////////////////////////////////////////////////// // StandardControls.cpp - demonstrates use of standard controls // // // // Jim Fawcett, CSE775 - Distributed Objects, Spring 2007 // /////////////////////////////////////////////////////////////////////////// /* ver 1.1 : 20 January 2008 - fixed bug in IDM_ABOUT processing by removing declaration of hInst and its initialization (was already correctly initialized at startup) ver 1.0 : 27 January 2007 - first release */ #include "stdafx.h" #include "StandardControls.h" #include #include #include #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); // //----< entry point defines message loop >--------------------------------- int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_STANDARDCONTROLS, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_STANDARDCONTROLS)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // //----< register window class for main window >---------------------------- ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_STANDARDCONTROLS)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_STANDARDCONTROLS); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } //----< create main window >----------------------------------------------- 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, 600, 400, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // //----< Measure dimensions of main window's client area >------------------ void FixClient(HWND hWnd, int& ClientX, int& ClientY, int& ClientWidth, int& ClientHeight) { RECT rect; GetClientRect(hWnd,&rect); ClientX = rect.left; ClientY = rect.top; ClientWidth = rect.right - rect.left; ClientHeight = rect.bottom - rect.top; } //----< set dimensions of Edit window to anchor in client area >----------- void FixEdit(HWND hWnd, int& EditX, int& EditY, int& EditWidth, int& EditHeight) { RECT rect; GetClientRect(hWnd,&rect); int EditTopMargin = 50; int EditBottomMargin = 100; EditWidth = rect.right - rect.left - 100; EditHeight = rect.bottom - rect.top - EditTopMargin - EditBottomMargin; EditX = rect.left + 50; EditY = rect.top + EditTopMargin; } //----< set dimensions of Button to anchor in client area >---------------- void FixButton(HWND hWnd, int& ButtonX, int& ButtonY, int& ButtonWidth, int& ButtonHeight) { RECT rect; GetClientRect(hWnd,&rect); ButtonWidth = 200; ButtonHeight = 50; int EditBottomMargin = 100; ButtonX = (rect.left + rect.right)/2 - ButtonWidth/2; ButtonY = rect.bottom - EditBottomMargin/2 - ButtonHeight/2; } // //----< Process messages >------------------------------------------------- LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc, hdcDB; HBITMAP hBitmap, hOldBitmap; HBRUSH hBrush, hOldBrush; // Client Parameters int ClientX, ClientY, TextX, TextX0 = 20; static int ClientWidth, ClientHeight; static RECT rect; static BOOL IsSizeDirty = FALSE; int CharWd = LOWORD(GetDialogBaseUnits()); int CharHt = HIWORD(GetDialogBaseUnits()); int textlen = 0; // Control Parameters int wmId, wmEvent; TCHAR* clkmsg = TEXT("Button Clicked"); std::wostringstream wSStrm; static std::wstring wMsg; static int i = 0, j = 0; // Button control const HMENU ButtonChildID = (HMENU)1; static HWND hButton = NULL; int ButtonX, ButtonY; int ButtonWidth, ButtonHeight; // Edit Control const HMENU EditChildID = (HMENU)2; static HWND hEdit = NULL; int EditX, EditY; int EditWidth, EditHeight; // switch (message) { case WM_CREATE: FixClient(hWnd,ClientX,ClientY,ClientWidth,ClientHeight); FixButton(hWnd,ButtonX,ButtonY,ButtonWidth,ButtonHeight); FixEdit(hWnd,EditX,EditY,EditWidth,EditHeight); hInst = ((LPCREATESTRUCT)lParam)->hInstance; hEdit = CreateWindow( TEXT("Edit"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL | CS_PARENTDC, EditX, EditY, EditWidth, EditHeight, hWnd, EditChildID, hInst, NULL ); hButton = CreateWindow( TEXT("button"), TEXT("Click Me!"), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | BS_NOTIFY, /* | CS_PARENTDC, */ ButtonX, ButtonY, ButtonWidth, ButtonHeight, hWnd, ButtonChildID, hInst, NULL ); break; // case WM_SIZE: IsSizeDirty = TRUE; //FixButton(hWnd,ButtonX,ButtonY,ButtonWidth,ButtonHeight); //FixEdit(hWnd,EditX,EditY,EditWidth,EditHeight); //MoveWindow(hButton, ButtonX,ButtonY,ButtonWidth,ButtonHeight,FALSE); //MoveWindow(hEdit,EditX,EditY,EditWidth,EditHeight,FALSE); i = 0; InvalidateRect(hWnd,NULL,FALSE); break; case WM_COMMAND: // Parse control messages: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch (wmId) { case ButtonChildID: // parse button messages switch(wmEvent) { case BN_CLICKED: MessageBox(NULL,L"been clicked",L"demo",MB_OK); FixClient(hWnd,ClientX,ClientY,ClientWidth,ClientHeight); hdc = GetDC(hWnd); textlen = (int)_tcslen(clkmsg); TextX = TextX0 + (textlen*CharWd)*(i++); if(TextX > ClientWidth - textlen*CharWd) { i = 0; TextX = TextX0; InvalidateRect(hWnd,NULL,TRUE); } TextOut(hdc,TextX,10,clkmsg,textlen); wSStrm << ++j; wMsg = std::wstring(L"\r\n Button Clicked\t\t#") + wSStrm.str() + wMsg; SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)wMsg.c_str()); break; case BN_DOUBLECLICKED: wSStrm << ++j; wMsg = std::wstring(L"\r\n Button Double-Clicked\t#") + wSStrm.str() + wMsg; SendMessage(hEdit,WM_SETTEXT,0,(LPARAM)wMsg.c_str()); break; } break; // parse menu selections case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; // case WM_PAINT: hdc = BeginPaint(hWnd, &ps); FixClient(hWnd,ClientX,ClientY,ClientWidth,ClientHeight); hdcDB = CreateCompatibleDC(hdc); hBitmap = CreateCompatibleBitmap(hdc,ClientWidth,ClientHeight); hOldBitmap = (HBITMAP)SelectObject(hdcDB,hBitmap); // paint background of client area if(IsSizeDirty == TRUE) { FixButton(hWnd,ButtonX,ButtonY,ButtonWidth,ButtonHeight); FixEdit(hWnd,EditX,EditY,EditWidth,EditHeight); MoveWindow(hButton, ButtonX,ButtonY,ButtonWidth,ButtonHeight,FALSE); MoveWindow(hEdit,EditX,EditY,EditWidth,EditHeight,FALSE); IsSizeDirty = FALSE; } hBrush = CreateSolidBrush(RGB(200,200,225)); hOldBrush = (HBRUSH)SelectObject(hdcDB,hBrush); GetClientRect(hWnd,&rect); // RedrawWindow(hWnd,&rect,NULL,RDW_NOERASE); Rectangle(hdcDB,rect.left,rect.top,rect.right,rect.bottom); BitBlt ( hdc,ClientX,ClientY,ClientWidth,ClientHeight, (HDC)hdcDB,ClientX,ClientY,SRCCOPY ); DeleteObject(hBrush); DeleteObject(hBitmap); DeleteObject(hdcDB); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // //----< handle messages for about box >------------------------------------ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }