Source code for Windows Status Bar control and test program; documentation at http://www.alumni.caltech.edu/~pje/status.html =============================== STATUS.CPP =============================== // Windows Status Bar #include const int MAX_TEXT_LENGTH = 127; const int MARGIN_WIDTH = 5; LRESULT CALLBACK StatusBarProc(HWND, UINT, WPARAM, LPARAM); /*----------------------------------------------------------------------------- This function registers the STATUSBAR class. It is called automatically when the program starts up. The external variables _hPrev and _hInstance duplicate the arguments hPrevInstance and hInstance, which are passed to WinMain(). If the startup code does not supply these external variables, you must pass the arguments to this function and call it explicitly before invoking any PICTUREBUTTON control. -----------------------------------------------------------------------------*/ extern HINSTANCE _hInstance; #ifndef WIN32 extern HINSTANCE _hPrev; #endif static void register_status_bar(void) { #ifndef WIN32 if (!_hPrev) #endif { WNDCLASS w; w.cbClsExtra = 0; w.cbWndExtra = sizeof(HGLOBAL); w.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH); w.hCursor = LoadCursor(NULL, IDC_ARROW); w.hIcon = NULL; w.hInstance = _hInstance; w.lpfnWndProc = StatusBarProc; w.lpszClassName = "STATUSBAR"; w.lpszMenuName = NULL; w.style = 0; RegisterClass(&w); } } #pragma startup register_status_bar struct STATUSBAR { int height; int width; long style; char text[MAX_TEXT_LENGTH]; int text_length; HFONT font; }; #ifdef WIN32 inline void MoveTo(HDC dc, int x, int y) { MoveToEx(dc, x, y, NULL); } #define GetWindowHandle GetWindowLong #define SetWindowHandle SetWindowLong #define GWH_HINSTANCE GWL_HINSTANCE #define HANDLE_WORD DWORD inline void PostClickedMessage(HWND handle) { PostMessage(GetParent(handle), WM_COMMAND, MAKELONG((WORD) GetMenu(handle), BN_CLICKED), (LPARAM) handle); } static DWORD GetTextExtent(HDC dc, LPCSTR string, int length) { SIZE size; GetTextExtentPoint(dc, string, length, &size); return MAKELONG(size.cx, size.cy); } #else #define GetWindowHandle GetWindowWord #define SetWindowHandle SetWindowWord #define GWH_HINSTANCE GWW_HINSTANCE #define HANDLE_WORD WORD inline void PostClickedMessage(HWND handle) { PostMessage(GetParent(handle), WM_COMMAND, GetMenu(handle), MAKELONG(handle, BN_CLICKED)); } #endif /*----------------------------------------------------------------------------- This function receives all messages directed to the control. -----------------------------------------------------------------------------*/ LRESULT CALLBACK StatusBarProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) { STATUSBAR far *p; HGLOBAL hp = (HGLOBAL) GetWindowHandle(handle, 0); if (hp != NULL) p = (STATUSBAR far *) GlobalLock(hp); switch (message) { case WM_CREATE: { hp = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(STATUSBAR)); if (hp == NULL) return -1L; p = (STATUSBAR far *) GlobalLock(hp); p->height = ((CREATESTRUCT far *) lParam)->cy; p->width = ((CREATESTRUCT far *) lParam)->cx; p->style = ((CREATESTRUCT far *) lParam)->style; { int i, c; for (i = 0; i < MAX_TEXT_LENGTH && (c = ((CREATESTRUCT far *) lParam)->lpszName[i]) != 0; i++) { p->text[i] = c; } p->text_length = i; } SetWindowHandle(handle, 0, (HANDLE_WORD) hp); GlobalUnlock(hp); return 0; } case WM_SIZE: { p->height = HIWORD(lParam); p->width = LOWORD(lParam); InvalidateRect(handle, NULL, TRUE); return 0; } case WM_SETTEXT: { int i, c; for (i = 0; i < MAX_TEXT_LENGTH && (c = ((char far *) lParam)[i]) != 0; i++) { p->text[i] = c; } p->text_length = i; InvalidateRect(handle, NULL, TRUE); GlobalUnlock(hp); return 0; } case WM_GETTEXT: { int i; for (i = 0; i < p->text_length && i+1 < (int) wParam; i++) ((char far *) lParam)[i] = p->text[i]; ((char far *) lParam)[i++] = 0; GlobalUnlock(hp); return (long) i; } case WM_SETFONT: p->font = (HFONT) wParam; InvalidateRect(handle, NULL, TRUE); GlobalUnlock(hp); return 0; case WM_GETFONT: GlobalUnlock(hp); return (long) (HANDLE_WORD) p->font; case WM_PAINT: { const COLORREF LIGHT_GRAY = RGB(192, 192, 192); const COLORREF DARK_GRAY = RGB(128, 128, 128); const COLORREF BLACK = RGB(0, 0, 0); PAINTSTRUCT paint; HDC dc = BeginPaint(handle, &paint); int height = p->height; int width = p->width; HPEN old_pen = SelectObject(dc, GetStockObject(BLACK_PEN)); HBRUSH old_brush = SelectObject(dc, GetStockObject(LTGRAY_BRUSH)); HPEN light_gray_pen = CreatePen(PS_SOLID, 1, LIGHT_GRAY); SelectObject(dc, light_gray_pen); Rectangle(dc, 0, 0, width, height); SelectObject(dc, GetStockObject(WHITE_PEN)); DeleteObject(light_gray_pen); MoveTo(dc, MARGIN_WIDTH+1, height-1-MARGIN_WIDTH); LineTo(dc, width-1-MARGIN_WIDTH, height-1-MARGIN_WIDTH); LineTo(dc, width-1-MARGIN_WIDTH, MARGIN_WIDTH); HPEN dark_gray_pen = CreatePen(PS_SOLID, 1, DARK_GRAY); SelectObject(dc, dark_gray_pen); MoveTo(dc, MARGIN_WIDTH, height-1-MARGIN_WIDTH); LineTo(dc, MARGIN_WIDTH, MARGIN_WIDTH); LineTo(dc, width-MARGIN_WIDTH, MARGIN_WIDTH); SelectObject(dc, old_pen); DeleteObject(dark_gray_pen); if (p->text_length != 0) { HFONT old_font; if (p->font != NULL) old_font = SelectObject(dc, p->font); SetBkColor(dc, LIGHT_GRAY); SetTextColor(dc, BLACK); TextOut(dc, MARGIN_WIDTH+1+LOWORD(GetTextExtent(dc, "m", 1))/2, (height - HIWORD(GetTextExtent(dc, p->text, p->text_length)))/2-1, p->text, p->text_length); if (p->font != NULL) SelectObject(dc, old_font); } SelectObject(dc, old_brush); EndPaint(handle, &paint); GlobalUnlock(hp); return 0; } case WM_DESTROY: GlobalUnlock(hp); GlobalFree(hp); return 0; } if (hp != NULL) GlobalUnlock(hp); return DefWindowProc(handle, message, wParam, lParam); } =============================== STATTEST.CPP =============================== // Windows Status Bar Control Test Program #include #include LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static char s[1024]; static HFONT font; switch (message) { case WM_CREATE: { return 0; } case WM_COMMAND: switch(wParam) { case 102: { GetDlgItemText(hwnd, 104, s, sizeof(s)); SetDlgItemText(hwnd, 101, s); SetDlgItemText(hwnd, 109, s); return 0; } case 103: DestroyWindow(hwnd); return 0; case 105: { if (font != NULL) DeleteObject(font); LOGFONT f; memset(&f, 0, sizeof(LOGFONT)); f.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; GetDlgItemText(hwnd, 104, f.lfFaceName, sizeof(f.lfFaceName)); font = CreateFontIndirect(&f); SendDlgItemMessage(hwnd, 109, WM_SETFONT, (WPARAM) font, 0L); return 0; } } break; case WM_CLOSE: if (font != NULL) DeleteObject(font); DestroyWindow(hwnd); return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefDlgProc (hwnd, message, wParam, lParam); } #pragma argsused int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { HWND hwnd; MSG msg; if (!hPrevInstance) { WNDCLASS wndclass; wndclass.style = 0; wndclass.lpfnWndProc = (WNDPROC) WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = DLGWINDOWEXTRA; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = NULL; wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "SBTEST"; RegisterClass (&wndclass); } hwnd = CreateDialog(hInstance, "SBTEST", 0, NULL); ShowWindow(hwnd, nCmdShow == SW_SHOWMAXIMIZED ? SW_SHOW : nCmdShow); //UpdateWindow(hwnd); while (GetMessage(&msg, NULL, 0, 0)) if (!IsDialogMessage (hwnd, &msg)) DispatchMessage (&msg); return msg.wParam; } =============================== STATTEST.RC =============================== SBTEST DIALOG 29, 69, 264, 125 STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CLASS "SBTEST" CAPTION "Status Bar Test Program" FONT 8, "MS Sans Serif" { CONTROL "Status Bar Test", 101, "STATUSBAR", 2 | WS_CHILD | WS_VISIBLE | WS_BORDER, 18, 12, 60, 36 CONTROL "Status Bar Test", 109, "STATUSBAR", 2 | WS_CHILD | WS_VISIBLE, 18, 60, 60, 36 EDITTEXT 104, 96, 8, 151, 17, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP PUSHBUTTON "To Status Bar", 102, 100, 33, 87, 23 PUSHBUTTON "Font", 105, 103, 74, 53, 17 PUSHBUTTON "Exit", 103, 211, 33, 33, 23 }