INFOCTRL.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:25k
源码类别:
Windows编程
开发平台:
Visual C++
- /******************************************************************************
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1993-1997 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- ******************************************************************************/
- /***************************************************************************
- * *
- * MODULE : infoctrl.c *
- * *
- * PURPOSE : Functions for the infoctrl control class *
- * *
- ***************************************************************************/
- /*
- * INFOCTRL.C
- *
- * This module implements a custom information display control which
- * can present up to 7 seperate strings of information at once and is
- * sizeable and moveable with the mouse.
- */
- #include <windows.h>
- #include <string.h>
- #include <tchar.h>
- #include <memory.h>
- #include "infoctrl.h"
- #include "track.h"
- TCHAR szClass[] = TEXT("InfoCtrl_class");
- DWORD cCreated = 0;
- TCHAR szNULL[] = TEXT("");
- INT cxMargin = 0;
- INT cyMargin = 0;
- HBRUSH hFocusBrush;
- LONG APIENTRY InfoCtrlWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
- VOID MyDrawText(HDC hdc, LPRECT lprc, PTSTR psz, DWORD wFormat);
- VOID DrawFocus(HDC hdc, HWND hwnd, DWORD style);
- INT CountWindows(HWND hwndParent);
- VOID GetCascadeWindowPos(HWND hwndParent, INT iWindow, LPRECT lprc);
- /****************************************************************************
- * *
- * FUNCTION : *
- * *
- * PURPOSE : *
- * *
- * RETURNS : *
- * *
- ****************************************************************************/
- HWND CreateInfoCtrl(
- LPTSTR pszCenter, // NULL is ok.
- INT x,
- INT y,
- INT cx,
- INT cy,
- HWND hwndParent,
- HANDLE hInst,
- LPTSTR pszUL, // NULLs here are fine.
- LPTSTR pszUC,
- LPTSTR pszUR,
- LPTSTR pszLL,
- LPTSTR pszLC,
- LPTSTR pszLR,
- DWORD style,
- HMENU id,
- DWORD dwUser)
- {
- INFOCTRL_DATA *picd;
- HWND hwnd;
- if (!cCreated) {
- WNDCLASS wc;
- TEXTMETRIC metrics;
- HDC hdc;
- wc.style = CS_VREDRAW | CS_HREDRAW;
- wc.lpfnWndProc = InfoCtrlWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = ICCBWNDEXTRA;
- wc.hInstance = hInst;
- wc.hIcon = NULL;
- wc.hCursor = NULL;
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
- wc.lpszMenuName = NULL;
- wc.lpszClassName = szClass;
- RegisterClass(&wc);
- hdc = GetDC(hwndParent);
- GetTextMetrics(hdc, &metrics);
- cyMargin = metrics.tmHeight;
- cxMargin = metrics.tmAveCharWidth * 2;
- ReleaseDC(hwndParent, hdc);
- hFocusBrush = CreateSolidBrush(RGB(0, 0, 255));
- }
- if (!(picd = (INFOCTRL_DATA *)LocalAlloc(LPTR, sizeof(INFOCTRL_DATA))))
- return(FALSE);
- if (pszCenter) {
- picd->pszCenter = (PTSTR)(PTSTR)LocalAlloc(LPTR,
- (_tcslen(pszCenter) + 1) * sizeof(TCHAR));
- _tcscpy(picd->pszCenter, pszCenter);
- } else {
- picd->pszCenter = NULL;
- }
- if (pszUL) {
- picd->pszUL = (PTSTR)(PTSTR)LocalAlloc(LPTR,
- (_tcslen(pszUL) + 1) * sizeof(TCHAR));
- _tcscpy(picd->pszUL, pszUL);
- } else {
- picd->pszUL = NULL;
- }
- if (pszUC) {
- picd->pszUC = (PTSTR)LocalAlloc(LPTR,
- (_tcslen(pszUC) + 1) * sizeof(TCHAR));
- _tcscpy(picd->pszUC, pszUC);
- } else {
- picd->pszUC = NULL;
- }
- if (pszUR) {
- picd->pszUR = (PTSTR)LocalAlloc(LPTR,
- (_tcslen(pszUR) + 1) * sizeof(TCHAR));
- _tcscpy(picd->pszUR, pszUR);
- } else {
- picd->pszUR = NULL;
- }
- if (pszLL) {
- picd->pszLL = (PTSTR)LocalAlloc(LPTR,
- (_tcslen(pszLL) + 1) * sizeof(TCHAR));
- _tcscpy(picd->pszLL, pszLL);
- } else {
- picd->pszLL = NULL;
- }
- if (pszLC) {
- picd->pszLC = (PTSTR)LocalAlloc(LPTR,
- (_tcslen(pszLC) + 1) * sizeof(TCHAR));
- _tcscpy(picd->pszLC, pszLC);
- } else {
- picd->pszLC = NULL;
- }
- if (pszLR) {
- picd->pszLR = (PTSTR)LocalAlloc(LPTR,
- (_tcslen(pszLR) + 1) * sizeof(TCHAR));
- _tcscpy(picd->pszLR, pszLR);
- } else {
- picd->pszLR = NULL;
- }
- picd->style = style;
- picd->hInst = hInst;
- if (hwnd = CreateWindow(szClass, szNULL,
- WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
- x, y, cx, cy, hwndParent, id, hInst, (LPTSTR)picd)) {
- cCreated++;
- SetWindowLong(hwnd, GWL_USER, dwUser);
- BringWindowToTop(hwnd);
- ShowWindow(hwnd, SW_SHOW);
- return(hwnd);
- }
- return(FALSE);
- }
- /****************************************************************************
- * *
- * FUNCTION : MyDrawText *
- * *
- * PURPOSE : Draws psz within lprc in hdc according to wFormat. *
- * *
- * RETURNS : Nothing. *
- * *
- ****************************************************************************/
- VOID MyDrawText(
- HDC hdc,
- LPRECT lprc,
- PTSTR psz,
- DWORD wFormat)
- {
- RECT rc;
- DWORD cx;
- if (psz == NULL || !*psz)
- return; // notin to draw dude.
- SetRect(&rc, 0, 0, 1, 0);
- DrawText(hdc, psz, -1, &rc, DT_CALCRECT | DT_NOCLIP | DT_SINGLELINE);
- cx = min(rc.right - rc.left, lprc->right - lprc->left);
- CopyRect(&rc, lprc);
- switch (wFormat & (DT_LEFT | DT_CENTER | DT_RIGHT)) {
- case DT_LEFT:
- rc.right = rc.left + cx;
- break;
- case DT_CENTER:
- cx = (rc.right - rc.left - cx) / 2;
- rc.right -= cx;
- rc.left += cx;
- break;
- case DT_RIGHT:
- rc.left = rc.right - cx;
- break;
- }
- DrawText(hdc, psz, -1, &rc, wFormat | DT_VCENTER);
- }
- /****************************************************************************
- * *
- * FUNCTION : InfoCtrlWndProc *
- * *
- * PURPOSE : Main window proc for info controls *
- * *
- * RETURNS : case dependent *
- * *
- ****************************************************************************/
- LONG APIENTRY InfoCtrlWndProc(
- HWND hwnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam)
- {
- INFOCTRL_DATA *picd;
- INT i;
- RECT rc;
- HDC hdc;
- switch (msg) {
- case WM_CREATE:
- /*
- * Info controls keep their information in the GWL_INFODATA window
- * word.
- */
- SetWindowLong(hwnd, GWL_INFODATA,
- (DWORD)(DWORD)(((LPCREATESTRUCT)lParam)->lpCreateParams));
- break;
- case WM_SIZE:
- /*
- * size the info control, updating the hittest rectangles.
- * The window is only allowed to get so small.
- */
- if ((short)LOWORD(lParam) < 2 * cxMargin || (short)HIWORD(lParam) < 2 * cyMargin) {
- MoveWindow(hwnd, 0, 0, max((short)LOWORD(lParam), 2 * cxMargin),
- max((short)HIWORD(lParam), 2 * cyMargin), TRUE);
- } else {
- picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
- SetRect(&picd->rcFocusUL, 0, 0, cxMargin, cyMargin);
- SetRect(&picd->rcFocusUR, (short)LOWORD(lParam) - cxMargin, 0,
- (short)LOWORD(lParam), cyMargin);
- SetRect(&picd->rcFocusLL, 0, (short)HIWORD(lParam) - cyMargin,
- cxMargin, (INT)HIWORD(lParam));
- SetRect(&picd->rcFocusLR, picd->rcFocusUR.left, picd->rcFocusLL.top,
- picd->rcFocusUR.right, picd->rcFocusLL.bottom);
- }
- break;
- case WM_DESTROY:
- /*
- * Info control death:
- *
- * Inform out parent - last chance to access GWL_USER.
- * Free our information if it still exists.
- * Free all strings associated with this control.
- */
- {
- PTSTR *ppsz;
- SendMessage(GetParent(hwnd), ICN_BYEBYE, (WPARAM)hwnd,
- GetWindowLong(hwnd, GWL_USER));
- SetWindowLong(hwnd, GWL_USER, 0);
- picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
- if (picd) {
- ppsz = &picd->pszUL;
- for (i = 0; i < 5; i++, ppsz++) {
- if (*ppsz) {
- LocalUnlock((HANDLE)*ppsz);
- *ppsz = (PTSTR)LocalFree((HANDLE)*ppsz);
- }
- }
- LocalUnlock((HANDLE)picd);
- LocalFree((HANDLE)picd);
- SetWindowLong(hwnd, GWL_INFODATA, 0);
- }
- }
- break;
- case WM_SETFOCUS:
- case WM_KILLFOCUS:
- /*
- * When focus changes:
- *
- * Alter our look apropriately
- * Bring ourselves to the top if necessary.
- * Inform our parent.
- * Repaint the focus portion of ourselves.
- * Call DefWindowProc()
- */
- picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
- if (picd != NULL) {
- if (picd->style & ICSTY_SHOWFOCUS) {
- if (msg == WM_SETFOCUS)
- picd->style |= ICSTY_HASFOCUS;
- else
- picd->style &= ~ICSTY_HASFOCUS;
- BringWindowToTop(hwnd);
- // notify parent
- SendMessage(GetParent(hwnd), ICN_HASFOCUS,
- msg == WM_SETFOCUS, (LPARAM)hwnd);
- } else {
- picd->style &= ~ICSTY_HASFOCUS;
- }
- hdc = GetDC(hwnd);
- DrawFocus(hdc, hwnd, picd->style);
- ReleaseDC(hwnd, hdc);
- }
- goto DoDWP;
- break;
- case WM_MOUSEMOVE:
- /*
- * Keep the cursor updated to show sizing or moving state.
- */
- {
- LPTSTR cursor;
- picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
- if (picd->style & ICSTY_SHOWFOCUS) {
- if ((INT)HIWORD(lParam) < cyMargin) {
- if ((short)LOWORD(lParam) < cxMargin) {
- cursor = IDC_SIZENWSE;
- } else if ((short)LOWORD(lParam) > picd->rcFocusUR.left) {
- cursor = IDC_SIZENESW;
- } else {
- cursor = IDC_SIZENS;
- }
- } else if ((INT)HIWORD(lParam) > picd->rcFocusLL.top) {
- if ((short)LOWORD(lParam) < cxMargin) {
- cursor = IDC_SIZENESW;
- } else if ((short)LOWORD(lParam) > picd->rcFocusUR.left) {
- cursor = IDC_SIZENWSE;
- } else {
- cursor = IDC_SIZENS;
- }
- } else {
- if ((short)LOWORD(lParam) < cxMargin) {
- cursor = IDC_SIZEWE;
- } else if ((short)LOWORD(lParam) > picd->rcFocusUR.left) {
- cursor = IDC_SIZEWE;
- } else {
- cursor = IDC_CROSS;
- }
- }
- } else {
- cursor = IDC_ARROW;
- }
- SetCursor(LoadCursor(NULL, cursor));
- }
- break;
- case WM_LBUTTONDOWN:
- /*
- * Track window according do mouse location.
- */
- picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
- if (picd->style & ICSTY_SHOWFOCUS) {
- DWORD fs = 0;
- if (!(picd->style & ICSTY_HASFOCUS)) {
- SetFocus(hwnd);
- }
- if ((short)HIWORD(lParam) < cyMargin) {
- fs = TF_TOP;
- } else if ((INT)HIWORD(lParam) > picd->rcFocusLL.top) {
- fs = TF_BOTTOM;
- }
- if ((short)LOWORD(lParam) < cxMargin) {
- fs |= TF_LEFT;
- } else if ((short)LOWORD(lParam) > picd->rcFocusUR.left) {
- fs |= TF_RIGHT;
- } else if (fs == 0) {
- fs = TF_MOVE;
- }
- GetClientRect(hwnd, &rc);
- ClientToScreen(hwnd, (LPPOINT)&rc.left);
- ClientToScreen(hwnd, (LPPOINT)&rc.right);
- ScreenToClient(GetParent(hwnd), (LPPOINT)&rc.left);
- ScreenToClient(GetParent(hwnd), (LPPOINT)&rc.right);
- if (TrackRect(picd->hInst, GetParent(hwnd),
- rc.left, rc.top, rc.right, rc.bottom,
- 2 * cxMargin, 2 * cyMargin,
- fs | TF_ALLINBOUNDARY, &rc)) {
- MoveWindow(hwnd, rc.left, rc.top, rc.right - rc.left,
- rc.bottom - rc.top, TRUE);
- }
- }
- break;
- case ICM_SETSTRING:
- /*
- * This message is sent when a info control string value is changeing.
- *
- * wParam = ICSID_ constant
- * lParam = new string.
- *
- * If new string is different from old, free old and allocate space
- * for new one and copy in.
- * Redraw invalidated part of info control.
- */
- {
- PTSTR *ppsz;
- picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
- ppsz = (PTSTR *)&picd->pszUL + wParam;
- if (lParam == 0)
- lParam = (DWORD)(LPTSTR)szNULL;
- if (*ppsz) {
- if (!_tcscmp(*ppsz, (LPTSTR)lParam)) {
- return 0;
- }
- LocalUnlock((HANDLE)*ppsz);
- *ppsz = (PTSTR)LocalFree((HANDLE)*ppsz);
- }
- if (lParam) {
- *ppsz = (PTSTR)LocalAlloc(LPTR,
- (_tcslen((LPTSTR)lParam) + 1) * sizeof(TCHAR));
- _tcscpy((LPTSTR)*ppsz, (LPTSTR)lParam);
- }
- GetClientRect(hwnd, &rc);
- switch (wParam) {
- case ICSID_UL:
- case ICSID_UC:
- case ICSID_UR:
- rc.bottom = cyMargin;
- break;
- case ICSID_LL:
- case ICSID_LC:
- case ICSID_LR:
- rc.top = rc.bottom - cyMargin;
- break;
- case ICSID_CENTER:
- InflateRect(&rc, -cxMargin, -cyMargin);
- break;
- }
- InvalidateRect(hwnd, &rc, TRUE);
- UpdateWindow(hwnd);
- }
- break;
- case WM_PAINT:
- /*
- * Paint ourselves.
- *
- * Draw frame.
- * Draw info strings.
- * Send ownerdraw message to parent if ICSTY_OWNERDRAW.
- */
- {
- PAINTSTRUCT ps;
- HANDLE brush;
- picd = (INFOCTRL_DATA *)GetWindowLong(hwnd, GWL_INFODATA);
- BeginPaint(hwnd, &ps);
- // erasure should have already been done for us.
- GetClientRect(hwnd, &rc);
- brush = GetStockObject(BLACK_BRUSH);
- InflateRect(&rc, -cxMargin / 2, -cyMargin / 2);
- FrameRect(ps.hdc, &rc, brush);
- InflateRect(&rc, cxMargin / 2, cyMargin / 2);
- SetRect(&rc, picd->rcFocusUL.right, 0, picd->rcFocusUR.left,
- cyMargin);
- MyDrawText(ps.hdc, &rc, picd->pszUR, DT_RIGHT);
- MyDrawText(ps.hdc, &rc, picd->pszUL, DT_LEFT);
- MyDrawText(ps.hdc, &rc, picd->pszUC, DT_CENTER);
- SetRect(&rc, picd->rcFocusLL.right, picd->rcFocusLL.top,
- picd->rcFocusLR.left, picd->rcFocusLR.bottom);
- MyDrawText(ps.hdc, &rc, picd->pszLR, DT_RIGHT);
- MyDrawText(ps.hdc, &rc, picd->pszLL, DT_LEFT);
- MyDrawText(ps.hdc, &rc, picd->pszLC, DT_CENTER);
- GetClientRect(hwnd, &rc);
- InflateRect(&rc, -cxMargin, -cyMargin);
- if (picd->style & ICSTY_OWNERDRAW) {
- OWNERDRAWPS odps;
- if (IntersectRect(&odps.rcPaint, &rc, &ps.rcPaint)) {
- if (IntersectClipRect(ps.hdc, rc.left, rc.top, rc.right,
- rc.bottom) != NULLREGION) {
- odps.rcBound = rc;
- odps.hdc = ps.hdc;
- odps.dwUser = GetWindowLong(hwnd, GWL_USER);
- SendMessage(GetParent(hwnd), ICN_OWNERDRAW,
- GetWindowLong(hwnd, GWL_ID), (DWORD)(LPTSTR)&odps);
- }
- }
- } else {
- MyDrawText(ps.hdc, &rc, picd->pszCenter, DT_LEFT | DT_WORDBREAK | DT_EXPANDTABS);
- }
- DrawFocus(ps.hdc, hwnd, picd->style);
- EndPaint(hwnd, &ps);
- }
- break;
- DoDWP:
- default:
- return (DefWindowProc(hwnd, msg, wParam, lParam));
- }
- return (0);
- }
- /****************************************************************************
- * *
- * FUNCTION : DrawFocus *
- * *
- * PURPOSE : To draw focus part of info control. *
- * *
- * RETURNS : nothing *
- * *
- ****************************************************************************/
- VOID DrawFocus(
- HDC hdc,
- HWND hwnd,
- DWORD style)
- {
- RECT rc;
- GetClientRect(hwnd, &rc);
- FrameRect(hdc, &rc, style & ICSTY_HASFOCUS ?
- hFocusBrush : GetStockObject(GRAY_BRUSH));
- }
- /****************************************************************************
- * *
- * FUNCTION : CountWindows *
- * *
- * PURPOSE : Counts how many info controls the parent of this window has*
- * *
- * RETURNS : the count. *
- * *
- ****************************************************************************/
- INT CountWindows(
- register HWND hwndParent)
- {
- INT cWindows = 0;
- register HWND hwnd;
- for (hwnd=GetWindow(hwndParent, GW_CHILD);
- hwnd;
- hwnd= GetWindow(hwnd, GW_HWNDNEXT)) {
- cWindows++;
- }
- return(cWindows);
- }
- /****************************************************************************
- * *
- * FUNCTION : GetCascadeWindowPos *
- * *
- * PURPOSE : Based on a window index and the parent window size, *
- * calculates where to place a cascaded window. *
- * *
- * RETURNS : rectangle in lprc. *
- * *
- ****************************************************************************/
- VOID GetCascadeWindowPos(
- HWND hwndParent,
- INT iWindow,
- LPRECT lprc)
- {
- RECT rc;
- INT cStack;
- register INT dxClient, dyClient;
- /* Compute the width and breadth of the situation. */
- GetClientRect(hwndParent, (LPRECT)&rc);
- dxClient = rc.right - rc.left;
- dyClient = rc.bottom - rc.top;
- /* How many windows per stack? */
- cStack = dyClient / (3 * cyMargin);
- lprc->right = dxClient - (cStack * cxMargin);
- lprc->bottom = dyClient - (cStack * cyMargin);
- cStack++; /* HACK!: Mod by cStack+1 */
- lprc->left = (iWindow % cStack) * cxMargin;
- lprc->top = (iWindow % cStack) * cyMargin;
- }
- /****************************************************************************
- * *
- * FUNCTION : MyCascadeChildWindows *
- * *
- * PURPOSE : Cascades all children of a parent window *
- * *
- * RETURNS : nothing *
- * *
- ****************************************************************************/
- VOID MyCascadeChildWindows(
- register HWND hwndParent)
- {
- INT i;
- INT cWindows;
- RECT rc;
- DWORD wFlags;
- register HWND hwndMove;
- HANDLE hDefer;
- cWindows = CountWindows(hwndParent);
- if (!cWindows)
- return;
- hwndMove = GetWindow(hwndParent, GW_CHILD);
- hDefer = BeginDeferWindowPos(cWindows);
- for (i=0; i < cWindows; i++) {
- GetCascadeWindowPos(hwndParent, i, (LPRECT)&rc);
- wFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS;
- /* Size the window. */
- hDefer = DeferWindowPos(hDefer,
- hwndMove, NULL,
- rc.left, rc.top,
- rc.right, rc.bottom,
- wFlags);
- hwndMove = GetWindow(hwndMove, GW_HWNDNEXT);
- }
- EndDeferWindowPos(hDefer);
- }
- /****************************************************************************
- * *
- * FUNCTION : TileChildWindows *
- * *
- * PURPOSE : Tiles all children of a parent window *
- * *
- * RETURNS : nothing. *
- * *
- ****************************************************************************/
- VOID TileChildWindows(
- register HWND hwndParent)
- {
- INT i;
- INT dx;
- INT dy;
- INT xRes;
- INT yRes;
- INT iCol;
- INT iRow;
- INT cCols;
- INT cRows;
- INT cExtra;
- INT cWindows;
- register HWND hwndMove;
- RECT rcClient;
- HANDLE hDefer;
- DWORD wFlags;
- cWindows = CountWindows(hwndParent);
- if (!cWindows)
- return;
- /* Compute the smallest nearest square. */
- for (i=2; i * i <= cWindows; i++);
- cRows = i - 1;
- cCols = cWindows / cRows;
- cExtra = cWindows % cRows;
- GetClientRect(hwndParent, (LPRECT)&rcClient);
- xRes = rcClient.right - rcClient.left;
- yRes = rcClient.bottom - rcClient.top;
- if (xRes<=0 || yRes<=0)
- return;
- hwndMove = GetWindow(hwndParent, GW_CHILD);
- hDefer = BeginDeferWindowPos(cWindows);
- for (iCol=0; iCol < cCols; iCol++) {
- if ((cCols-iCol) <= cExtra)
- cRows++;
- for (iRow=0; iRow < cRows; iRow++) {
- dx = xRes / cCols;
- dy = yRes / cRows;
- wFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS;
- /* Position and size the window. */
- hDefer = DeferWindowPos(hDefer, hwndMove, NULL,
- dx * iCol,
- dy * iRow,
- dx,
- dy,
- wFlags);
- hwndMove = GetWindow(hwndMove, GW_HWNDNEXT);
- }
- if ((cCols-iCol) <= cExtra) {
- cRows--;
- cExtra--;
- }
- }
- EndDeferWindowPos(hDefer);
- }