/* File: D:\WACKER\tdll\sidebar.c (Created: 10-Mar-1995) * * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI * All rights reserved * * $Revision: 12 $ * $Date: 4/16/02 2:41p $ */ #include #include "stdtyp.h" #include "globals.h" #include "assert.h" #include "session.h" #include #include #include "htchar.h" #define INDENT 3 #define SIDEBAR_CLASS "sidebar class" #define LOSHORT(x) ((short)LOWORD(x)) #define HISHORT(x) ((short)HIWORD(x)) static void SB_WM_SIZE(const HWND hwnd, const int cx, const int cy); LRESULT CALLBACK SidebarButtonProc(HWND hwnd, UINT uMsg, WPARAM wPar, LPARAM lPar); // I know, a static. Bad news but not really. Since this is just for // the minitel I didn't want to screw around with local atoms. If we // ever decide that this stuff will be used for more general purposes, // we can put in the atoms // static WNDPROC fpSidebarButtonProc; /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * CreateSidebar * * DESCRIPTION: * Creates a sidebar. What's a sidebar you say? Its a bar with buttons * on it running down the left side of the session window. It is used * only for the minitel emulator and displays buttons specific to that * emulator. * * ARGUMENTS: * hwndSession - session window handle. * * RETURNS: * sidebar window handle. * * AUTHOR: Mike Ward, 10-Mar-1995 */ HWND CreateSidebar(const HWND hwndSession, const HSESSION hSession) { UINT i; TCHAR ach[100]; HWND hwnd; HWND hwndSideBar; SIZE sz; LONG cx = 0; LONG cy = 0; HDC hdc; HGDIOBJ hFont; // Figure out the longest string to size things by // hdc = GetDC(hwndSession); hFont = GetStockObject(DEFAULT_GUI_FONT); SelectObject(hdc, hFont); for (i = 0 ; i < 9 ; ++i) { LoadString(glblQueryDllHinst(), IDS_SIDEBAR_INDEX+i, ach, sizeof(ach) / sizeof(TCHAR)); GetTextExtentPoint32(hdc, ach, StrCharGetStrLength(ach), &sz); cx = max(sz.cx, cx); cy = max(sz.cy, cy); } ReleaseDC(hwndSession, hdc); // Good button size is 1.5 times text height. Also add padding // for horizontal diretion. // cx += WINDOWSBORDERWIDTH * 10; cy = (LONG)(cy * 1.5); // Create sidebar window with proper x dimension // hwndSideBar = CreateWindowEx(WS_EX_CLIENTEDGE, SIDEBAR_CLASS, 0, WS_CHILD, 0, 0, cx+2+(2*INDENT), 100, hwndSession, (HMENU)IDC_SIDEBAR_WIN, glblQueryDllHinst(), hSession); // Important: Set fpSidebarButtonProc to zero here. It may have // been initialized by an earlier instance. We could set it to // zero in the WM_DESTROY but then I'ld have to keep a list of // button window handles which I don't want to do here. // fpSidebarButtonProc = 0; // Create buttons for sidebar and postion with text // for (i = 0 ; i < 9 ; ++i) { LoadString(glblQueryDllHinst(), IDS_SIDEBAR_INDEX+i, ach, sizeof(ach) / sizeof(TCHAR)); hwnd = CreateWindowEx(0, "BUTTON", ach, WS_CHILD | WS_VISIBLE | BS_LEFT | BS_PUSHBUTTON, 0, 0, cx, cy, hwndSideBar, (HMENU)IntToPtr(IDM_MINITEL_INDEX+i), glblQueryDllHinst(), 0); if ( hwnd == NULL ) { assert( hwnd ); return 0; } SendMessage(hwnd, WM_SETFONT, (WPARAM)hFont, 0); MoveWindow(hwnd, INDENT, ((int)i*(cy+INDENT))+INDENT, cx, cy, FALSE); // Need to subclass the buttons so that they don't get the focus // rectangle left on them. This will require an atom to so that // we can get the original button proc. // if (fpSidebarButtonProc == 0) fpSidebarButtonProc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC); if (fpSidebarButtonProc) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)SidebarButtonProc); } return hwndSideBar; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * SidebarProc * * DESCRIPTION: * Sidebar window proc. * * AUTHOR: Mike Ward, 10-Mar-1995 */ LRESULT CALLBACK SidebarProc(HWND hwnd, UINT uMsg, WPARAM wPar, LPARAM lPar) { HSESSION hSession; switch (uMsg) { case WM_CREATE: // Save session handle for later // SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT)lPar)->lpCreateParams); return 0; case WM_COMMAND: switch (LOWORD(wPar)) { case IDM_MINITEL_INDEX: case IDM_MINITEL_CANCEL: case IDM_MINITEL_PREVIOUS: case IDM_MINITEL_REPEAT: case IDM_MINITEL_GUIDE: case IDM_MINITEL_CORRECT: case IDM_MINITEL_NEXT: case IDM_MINITEL_SEND: case IDM_MINITEL_CONFIN: if (HIWORD(wPar) == BN_CLICKED) { hSession = (HSESSION)GetWindowLongPtr(hwnd, GWLP_USERDATA); emuMinitelSendKey(sessQueryEmuHdl(hSession), LOWORD(wPar)); SetFocus(sessQueryHwnd(hSession)); } break; default: break; } break; case WM_SIZE: SB_WM_SIZE(hwnd, LOSHORT(lPar), HISHORT(lPar)); return 0; default: break; } return DefWindowProc(hwnd, uMsg, wPar, lPar); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * SB_WM_SIZE * * DESCRIPTION: * Sizing logic for sidebar. This routine sizes the sidebar vertically * to the session window. * * ARGUMENTS: * hwnd - sidebar window handle * cx - x size of window * cy - y size of window * * RETURNS: * void * * AUTHOR: Mike Ward, 10-Mar-1995 */ static void SB_WM_SIZE(const HWND hwnd, const int cx, const int cy) { RECT rc; RECT rcSB; RECT rcTmp; const HSESSION hSession = (HSESSION)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); const HWND hwndToolbar = sessQueryHwndToolbar(hSession); const HWND hwndStatusbar = sessQueryHwndStatusbar(hSession); if (cx != 0 || cy != 0) return; GetWindowRect(hwnd, &rcSB); GetClientRect(GetParent(hwnd), &rc); if (IsWindow(hwndToolbar) && IsWindowVisible(hwndToolbar)) { GetWindowRect(hwndToolbar, &rcTmp); rc.top += (rcTmp.bottom - rcTmp.top); } if (IsWindow(hwndStatusbar) && IsWindowVisible(hwndStatusbar)) { GetWindowRect(hwndStatusbar, &rcTmp); rc.bottom -= (rcTmp.bottom - rcTmp.top); rc.bottom += 2 * WINDOWSBORDERHEIGHT; } MoveWindow(hwnd, rc.left, rc.top, rcSB.right-rcSB.left, rc.bottom-rc.top, TRUE); return; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * RegisterSidebarClass * * DESCRIPTION: * Registers the sidebar window class used for Minitel. * * ARGUMENTS: * hInstance - instance handle of program. * * RETURNS: * TRUE/FALSE * * AUTHOR: Mike Ward, 10-Mar-1995 */ BOOL RegisterSidebarClass(const HINSTANCE hInstance) { WNDCLASSEX wc; memset(&wc, 0, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); if (GetClassInfoEx(hInstance, SIDEBAR_CLASS, &wc) == FALSE) { wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = SidebarProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(LONG_PTR); wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); wc.lpszMenuName = NULL; wc.lpszClassName = SIDEBAR_CLASS; wc.hIconSm = NULL; if (RegisterClassEx(&wc) == FALSE) { assert(FALSE); return FALSE; } } return TRUE; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * SidebarButtonProc * * DESCRIPTION: * Don't you just love windows. I don't want the focus to ever remain * on the Sidebar but to do this with standard buttons I have to subclass * them. * * AUTHOR: Mike Ward, 13-Mar-1995 */ LRESULT CALLBACK SidebarButtonProc(HWND hwnd, UINT uMsg, WPARAM wPar, LPARAM lPar) { HSESSION hSession; POINT pt; RECT rc; switch (uMsg) { case WM_LBUTTONUP: hSession = (HSESSION)GetWindowLongPtr(GetParent(hwnd), GWLP_USERDATA); // Well, its never simple. If the user clicks on the button, we don't // reset focus else our sidebar never receives the notification. If // the user holds the button down however and drags off the button // and then lets up (button up not on the button) then we need to // set focus. - mrw. // pt.x = LOWORD(lPar); pt.y = HIWORD(lPar); GetClientRect(hwnd, &rc); if (!PtInRect(&rc, pt)) SetFocus(sessQueryHwnd(hSession)); break; default: break; } return CallWindowProc(fpSidebarButtonProc, hwnd, uMsg, wPar, lPar); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- * FUNCTION: * UnregisterSidebarClass * * DESCRIPTION: * Registers the sidebar window class used for Minitel. * * ARGUMENTS: * hInstance - instance handle of program. * * RETURNS: * TRUE/FALSE * * AUTHOR: Mike Ward, 10-Mar-1995 */ BOOL UnregisterSidebarClass(const HINSTANCE hInstance) { return UnregisterClass(SIDEBAR_CLASS, hInstance); }