#include #include #include #include "status.h" /* for compiling under win3.0 - we don't have this attribute */ #ifndef COLOR_BTNHIGHLIGHT #define COLOR_BTNHIGHLIGHT 20 #endif #ifdef _WIN32 typedef WNDPROC LPWNDPROC; #else typedef long (FAR PASCAL *LPWNDPROC)(); #endif // user defined messages for the status window enum { WM_DELAYEDSETTEXT = WM_USER, }; // class names for status bar and static text windows TCHAR szStatusClass[] = TEXT("StatusClass"); TCHAR szText[] = TEXT("SText"); int gStatusStdHeight; // based on font metrics static HANDLE ghFont; static HBRUSH ghbrHL, ghbrShadow; extern HWND ghWndStatus; /* Function Prototypes */ LONG FAR PASCAL statusWndProc(HWND hwnd, unsigned msg, UINT wParam, LONG lParam); LONG FAR PASCAL fnText(HWND, unsigned, UINT, LONG); static VOID NEAR PASCAL PaintText(HWND hwnd, HDC hdc); /* * create the brushes we need */ void statusCreateTools(void) { HDC hdc; TEXTMETRIC tm; HFONT hfont; ghbrHL = CreateSolidBrush(GetSysColor(COLOR_BTNHIGHLIGHT)); ghbrShadow = CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW)); /* Create the font we'll use for the status bar - use system as default */ ghFont = CreateFont(12,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_MODERN,TEXT("Helv")); if(ghFont == NULL) ghFont = GetStockObject(SYSTEM_FONT); hdc = GetDC(NULL); hfont = SelectObject(hdc, ghFont); GetTextMetrics(hdc, &tm); SelectObject(hdc, hfont); ReleaseDC(NULL, hdc); gStatusStdHeight = tm.tmHeight * 3 / 2; } void statusDeleteTools(void) { DeleteObject(ghbrHL); DeleteObject(ghbrShadow); DeleteObject(ghFont); } /*-------------------------------------------------------------+ | statusInit - initialize for status window, register the | | Window's class. | | | +--------------------------------------------------------------*/ #pragma alloc_text(INIT_TEXT, statusInit) BOOL statusInit(HANDLE hInst, HANDLE hPrev) { WNDCLASS cls; statusCreateTools(); if (!hPrev) { cls.hCursor = LoadCursor(NULL, IDC_ARROW); cls.hIcon = NULL; cls.lpszMenuName = NULL; cls.lpszClassName = szStatusClass; cls.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); cls.hInstance = hInst; cls.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; cls.lpfnWndProc = statusWndProc; cls.cbClsExtra = 0; cls.cbWndExtra = 0; if (!RegisterClass(&cls)) return FALSE; cls.hCursor = LoadCursor(NULL,IDC_ARROW); cls.hIcon = NULL; cls.lpszMenuName = NULL; cls.lpszClassName = (LPTSTR)szText; cls.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); cls.hInstance = hInst; cls.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; cls.lpfnWndProc = (LPWNDPROC)fnText; cls.cbClsExtra = 0; cls.cbWndExtra = 0; if (!RegisterClass(&cls)) return FALSE; } return(TRUE); } /* * returns the recommended height for a status bar based on the * character dimensions of the font used */ int statusGetHeight(void) { return(gStatusStdHeight); } /*-------------------------------------------------------------+ | statusUpdate - update the status line | | | | The argument can either be NULL, a string, or a resource ID | | cast to a LPCSTR with MAKEINTRESOURCE. | +--------------------------------------------------------------*/ extern void statusUpdate(LPCTSTR lpszFormat, ...) { TCHAR ach[180]; HWND hwndtext; if ((lpszFormat != NULL) && (HIWORD((DWORD) lpszFormat) == 0)) LoadString(GetWindowInstance(ghWndStatus), LOWORD((DWORD) lpszFormat), ach, sizeof(ach)); else if(!lpszFormat) ach[0] = 0; else { va_list args; va_start(args, lpszFormat); wvsprintf(ach, lpszFormat, args); va_end(args); } hwndtext = GetDlgItem(ghWndStatus, 1); SetWindowText(hwndtext, ach); } /*-------------------------------------------------------------+ | statusUpdate - update the status line | | | | The argument can either be NULL, a string, or a resource ID | | cast to a LPCSTR with MAKEINTRESOURCE. | +--------------------------------------------------------------*/ extern void statusUpdateA(LPCSTR lpszFormat, ...) { char ach[180]; HWND hwndtext; if ((lpszFormat != NULL) && (HIWORD((DWORD) lpszFormat) == 0)) LoadStringA(GetWindowInstance(ghWndStatus), LOWORD((DWORD) lpszFormat), ach, sizeof(ach)); else if(!lpszFormat) ach[0] = 0; else { va_list args; va_start(args, lpszFormat); wvsprintfA(ach, lpszFormat, args); va_end(args); } hwndtext = GetDlgItem(ghWndStatus, 1); SetWindowTextA(hwndtext, ach); } /*-------------------------------------------------------------+ | statusUpdateDelayed - update the status line using | | PostMessage. This is safe to call from inside a callback | | because it will not cause a lockup | | | | The argument can either be NULL, a string, or a resource ID | | cast to a LPCSTR with MAKEINTRESOURCE. | +--------------------------------------------------------------*/ void statusUpdateDelayed(LPCTSTR lpszFormat, ...) { // keep this static because i am posting messages static TCHAR ach[180]; HWND hwndtext; if ((lpszFormat != NULL) && (HIWORD((DWORD) lpszFormat) == 0)) LoadString(GetWindowInstance(ghWndStatus), LOWORD((DWORD) lpszFormat), ach, sizeof(ach)); else if(!lpszFormat) ach[0] = 0; else { va_list args; va_start(args, lpszFormat); wvsprintf(ach, lpszFormat, args); va_end(args); } hwndtext = GetDlgItem(ghWndStatus, 1); // Note that PostMessage might fail. I am not checking whether // the message was posted or not because this is not a very important message // Note that WM_SETTEXT cannot be sent using PostMessage! To overcome this, // we have to use an user-defined message // Note that the ach buffer can be overwritten since we are interested // only in the last message! PostMessage(hwndtext, WM_DELAYEDSETTEXT, 0, (LPARAM)(LPCTSTR)ach); } /*-------------------------------------------------------------+ | statusWndProc - window proc for status window | | | +--------------------------------------------------------------*/ LONG FAR PASCAL statusWndProc(HWND hwnd, unsigned msg, UINT wParam, LONG lParam) { PAINTSTRUCT ps; HDC hdc; HWND hwndSText; switch(msg) { case WM_CREATE: /* we need to create the static text control for the status bar */ hwndSText = CreateWindow(szText,TEXT(""),WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,0, 0, 0, 0, hwnd,(HMENU) 1,GetWindowInstance(hwnd),NULL); if(!hwndSText) return(-1); break; case WM_DESTROY: statusDeleteTools(); break; case WM_SIZE: { RECT rc; GetClientRect(hwnd, &rc); MoveWindow(GetDlgItem(hwnd, 1),2,1,rc.right - 4,rc.bottom - 2,TRUE); break; } case WM_PAINT: hdc = BeginPaint(hwnd, &ps); // only the background and the child window need painting EndPaint(hwnd, &ps); break; case WM_SYSCOLORCHANGE: statusDeleteTools(); statusCreateTools(); break; case WM_ERASEBKGND: break; } return(DefWindowProc(hwnd, msg, wParam, lParam)); } /* * window proc for static text window */ LONG FAR PASCAL fnText(HWND hwnd, UINT msg, UINT wParam, LONG lParam ) { PAINTSTRUCT ps; switch (msg) { case WM_DELAYEDSETTEXT: if(lParam) SetWindowText(hwnd, (LPCTSTR)lParam); break; case WM_SETTEXT: DefWindowProc(hwnd, msg, wParam, lParam); InvalidateRect(hwnd,NULL,FALSE); UpdateWindow(hwnd); return(0L); case WM_ERASEBKGND: return(0L); case WM_PAINT: BeginPaint(hwnd, &ps); PaintText(hwnd, ps.hdc); EndPaint(hwnd, &ps); return(0L); } return(DefWindowProc(hwnd, msg, wParam, lParam)); } /*-------------------------------------------------------------+ | PaintText - paint the shadowed static text field. | | | +--------------------------------------------------------------*/ VOID NEAR PASCAL PaintText(HWND hwnd, HDC hdc) { RECT rc; TCHAR ach[128]; int len; int dx, dy; RECT rcFill; HFONT hfontOld; HBRUSH hbrSave; GetClientRect(hwnd, &rc); memset(ach,0,sizeof(ach)); len = GetWindowText(hwnd,ach,sizeof(ach)/sizeof(TCHAR)); SetBkColor(hdc, GetSysColor(COLOR_BTNFACE)); SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT)); hfontOld = SelectObject(hdc, ghFont); rcFill.left = rc.left + 1; rcFill.right = rc.right - 1; rcFill.top = rc.top + 1; rcFill.bottom = rc.bottom - 1; ExtTextOut(hdc,4,1,ETO_OPAQUE,&rcFill,ach,len,NULL); dx = rc.right - rc.left; dy = rc.bottom - rc.top; hbrSave = SelectObject(hdc, ghbrShadow); PatBlt(hdc, rc.left, rc.top, 1, dy, PATCOPY); PatBlt(hdc, rc.left, rc.top, dx, 1, PATCOPY); SelectObject(hdc, ghbrHL); PatBlt(hdc, rc.right-1, rc.top+1, 1, dy-1, PATCOPY); PatBlt(hdc, rc.left+1, rc.bottom -1, dx-1, 1, PATCOPY); if(hfontOld) SelectObject(hdc, hfontOld); if(hbrSave) SelectObject(hdc, hbrSave); return; }