Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmap.cGo to the documentation of this file.00001 /* 00002 * PROJECT: ReactOS Character Map 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: base/applications/charmap/map.c 00005 * PURPOSE: class implementation for painting glyph region 00006 * COPYRIGHT: Copyright 2007 Ged Murphy <gedmurphy@reactos.org> 00007 * 00008 */ 00009 00010 #include <precomp.h> 00011 00012 static const WCHAR szMapWndClass[] = L"FontMapWnd"; 00013 static const WCHAR szLrgCellWndClass[] = L"LrgCellWnd"; 00014 00015 static 00016 VOID 00017 TagFontToCell(PCELL pCell, 00018 WCHAR ch) 00019 { 00020 pCell->ch = ch; 00021 } 00022 00023 00024 static 00025 VOID 00026 SetGrid(PMAP infoPtr) 00027 { 00028 INT x, y; 00029 00030 for (y = 0; y < YCELLS; y++) 00031 for (x = 0; x < XCELLS; x++) 00032 { 00033 infoPtr->Cells[y][x].CellExt.left = x * infoPtr->CellSize.cx + 1; 00034 infoPtr->Cells[y][x].CellExt.top = y * infoPtr->CellSize.cy + 1; 00035 infoPtr->Cells[y][x].CellExt.right = (x + 1) * infoPtr->CellSize.cx + 2; 00036 infoPtr->Cells[y][x].CellExt.bottom = (y + 1) * infoPtr->CellSize.cy + 2; 00037 00038 CopyRect(&infoPtr->Cells[y][x].CellInt, 00039 &infoPtr->Cells[y][x].CellExt); 00040 00041 InflateRect(&infoPtr->Cells[y][x].CellInt, 00042 -1, 00043 -1); 00044 } 00045 } 00046 00047 static 00048 VOID 00049 DrawActiveCell(PMAP infoPtr, 00050 HDC hdc) 00051 { 00052 Rectangle(hdc, 00053 infoPtr->pActiveCell->CellInt.left, 00054 infoPtr->pActiveCell->CellInt.top, 00055 infoPtr->pActiveCell->CellInt.right, 00056 infoPtr->pActiveCell->CellInt.bottom); 00057 00058 } 00059 00060 00061 static 00062 VOID 00063 DrawGrid(PMAP infoPtr, 00064 PAINTSTRUCT *ps) 00065 { 00066 INT x, y; 00067 RECT rc; 00068 PCELL Cell; 00069 00070 for (y = 0; y < YCELLS; y++) 00071 for (x = 0; x < XCELLS; x++) 00072 { 00073 Cell = &infoPtr->Cells[y][x]; 00074 00075 if (!IntersectRect(&rc, 00076 &ps->rcPaint, 00077 &Cell->CellExt)) 00078 { 00079 continue; 00080 } 00081 00082 Rectangle(ps->hdc, 00083 Cell->CellExt.left, 00084 Cell->CellExt.top, 00085 Cell->CellExt.right, 00086 Cell->CellExt.bottom); 00087 00088 if (infoPtr->pActiveCell == Cell) 00089 { 00090 DrawActiveCell(infoPtr, ps->hdc); 00091 } 00092 } 00093 } 00094 00095 00096 static 00097 VOID 00098 FillGrid(PMAP infoPtr, 00099 PAINTSTRUCT *ps) 00100 { 00101 HFONT hOldFont; 00102 WCHAR ch; 00103 INT x, y; 00104 RECT rc; 00105 PCELL Cell; 00106 00107 hOldFont = SelectObject(ps->hdc, 00108 infoPtr->hFont); 00109 00110 for (y = 0; y < YCELLS; y++) 00111 for (x = 0; x < XCELLS; x++) 00112 { 00113 Cell = &infoPtr->Cells[y][x]; 00114 00115 if (!IntersectRect(&rc, 00116 &ps->rcPaint, 00117 &Cell->CellExt)) 00118 { 00119 continue; 00120 } 00121 00122 ch = (WCHAR)((XCELLS * (y + infoPtr->iYStart)) + x); 00123 00124 TagFontToCell(Cell, ch); 00125 00126 DrawTextW(ps->hdc, 00127 &ch, 00128 1, 00129 &Cell->CellInt, 00130 DT_CENTER | DT_VCENTER | DT_SINGLELINE); 00131 } 00132 00133 SelectObject(ps->hdc, 00134 hOldFont); 00135 } 00136 00137 00138 static 00139 BOOL 00140 CreateLargeCell(PMAP infoPtr) 00141 { 00142 RECT rLarge; 00143 00144 CopyRect(&rLarge, 00145 &infoPtr->pActiveCell->CellExt); 00146 00147 MapWindowPoints(infoPtr->hMapWnd, 00148 infoPtr->hParent, 00149 (VOID*)&rLarge, 00150 2); 00151 00152 InflateRect(&rLarge, 00153 XLARGE - XCELLS, 00154 YLARGE - YCELLS); 00155 00156 infoPtr->hLrgWnd = CreateWindowExW(0, 00157 szLrgCellWndClass, 00158 NULL, 00159 WS_CHILDWINDOW | WS_VISIBLE, 00160 rLarge.left, 00161 rLarge.top, 00162 rLarge.right - rLarge.left, 00163 rLarge.bottom - rLarge.top, 00164 infoPtr->hParent, 00165 NULL, 00166 hInstance, 00167 infoPtr); 00168 if (!infoPtr->hLrgWnd) 00169 return FALSE; 00170 00171 return TRUE; 00172 } 00173 00174 00175 static 00176 VOID 00177 MoveLargeCell(PMAP infoPtr) 00178 { 00179 RECT rLarge; 00180 00181 CopyRect(&rLarge, 00182 &infoPtr->pActiveCell->CellExt); 00183 00184 MapWindowPoints(infoPtr->hMapWnd, 00185 infoPtr->hParent, 00186 (VOID*)&rLarge, 00187 2); 00188 00189 InflateRect(&rLarge, 00190 XLARGE - XCELLS, 00191 YLARGE - YCELLS); 00192 00193 MoveWindow(infoPtr->hLrgWnd, 00194 rLarge.left, 00195 rLarge.top, 00196 rLarge.right - rLarge.left, 00197 rLarge.bottom - rLarge.top, 00198 TRUE); 00199 00200 InvalidateRect(infoPtr->hLrgWnd, 00201 NULL, 00202 TRUE); 00203 } 00204 00205 00206 static 00207 VOID 00208 SetFont(PMAP infoPtr, 00209 LPWSTR lpFontName) 00210 { 00211 HDC hdc; 00212 00213 /* Destroy Zoom window, since it was created with older font */ 00214 DestroyWindow(infoPtr->hLrgWnd); 00215 infoPtr->hLrgWnd = NULL; 00216 00217 if (infoPtr->hFont) 00218 DeleteObject(infoPtr->hFont); 00219 00220 ZeroMemory(&infoPtr->CurrentFont, 00221 sizeof(LOGFONTW)); 00222 00223 hdc = GetDC(infoPtr->hMapWnd); 00224 infoPtr->CurrentFont.lfHeight = GetDeviceCaps(hdc, 00225 LOGPIXELSY) / 5; 00226 ReleaseDC(infoPtr->hMapWnd, hdc); 00227 00228 infoPtr->CurrentFont.lfCharSet = DEFAULT_CHARSET; 00229 wcscpy(infoPtr->CurrentFont.lfFaceName, 00230 lpFontName); 00231 00232 infoPtr->hFont = CreateFontIndirectW(&infoPtr->CurrentFont); 00233 00234 InvalidateRect(infoPtr->hMapWnd, 00235 NULL, 00236 TRUE); 00237 00238 /* Test if zoom window must be reopened */ 00239 if (infoPtr->pActiveCell != NULL && 00240 infoPtr->pActiveCell->bLarge) 00241 { 00242 CreateLargeCell(infoPtr); 00243 } 00244 } 00245 00246 00247 static 00248 LRESULT 00249 NotifyParentOfSelection(PMAP infoPtr, 00250 UINT code, 00251 WCHAR ch) 00252 { 00253 LRESULT Ret = 0; 00254 00255 if (infoPtr->hParent != NULL) 00256 { 00257 DWORD dwIdc = GetWindowLongPtr(infoPtr->hMapWnd, GWLP_ID); 00258 /* 00259 * Push directly into the event queue instead of waiting 00260 * the parent to be unlocked. 00261 * High word of LPARAM is still available for future needs... 00262 */ 00263 Ret = PostMessage(infoPtr->hParent, 00264 WM_COMMAND, 00265 MAKELPARAM((WORD)dwIdc, (WORD)code), 00266 (LPARAM)LOWORD(ch)); 00267 } 00268 00269 return Ret; 00270 } 00271 00272 00273 static 00274 VOID 00275 OnClick(PMAP infoPtr, 00276 WORD ptx, 00277 WORD pty) 00278 { 00279 POINT pt; 00280 INT x, y; 00281 00282 pt.x = ptx; 00283 pt.y = pty; 00284 00285 for (x = 0; x < XCELLS; x++) 00286 for (y = 0; y < YCELLS; y++) 00287 { 00288 if (PtInRect(&infoPtr->Cells[y][x].CellInt, 00289 pt)) 00290 { 00291 /* if the cell is not already active */ 00292 if (!infoPtr->Cells[y][x].bActive) 00293 { 00294 /* set previous active cell to inactive */ 00295 if (infoPtr->pActiveCell) 00296 { 00297 /* invalidate normal cells, required when 00298 * moving a small active cell via keyboard */ 00299 if (!infoPtr->pActiveCell->bLarge) 00300 { 00301 InvalidateRect(infoPtr->hMapWnd, 00302 &infoPtr->pActiveCell->CellInt, 00303 TRUE); 00304 } 00305 00306 infoPtr->pActiveCell->bActive = FALSE; 00307 infoPtr->pActiveCell->bLarge = FALSE; 00308 } 00309 00310 /* set new cell to active */ 00311 infoPtr->pActiveCell = &infoPtr->Cells[y][x]; 00312 infoPtr->pActiveCell->bActive = TRUE; 00313 infoPtr->pActiveCell->bLarge = TRUE; 00314 if (infoPtr->hLrgWnd) 00315 MoveLargeCell(infoPtr); 00316 else 00317 CreateLargeCell(infoPtr); 00318 } 00319 else 00320 { 00321 /* flick between large and small */ 00322 if (infoPtr->pActiveCell->bLarge) 00323 { 00324 DestroyWindow(infoPtr->hLrgWnd); 00325 infoPtr->hLrgWnd = NULL; 00326 } 00327 else 00328 { 00329 CreateLargeCell(infoPtr); 00330 } 00331 00332 infoPtr->pActiveCell->bLarge = (infoPtr->pActiveCell->bLarge) ? FALSE : TRUE; 00333 } 00334 00335 break; 00336 } 00337 } 00338 } 00339 00340 00341 static 00342 BOOL 00343 OnCreate(PMAP infoPtr, 00344 HWND hwnd, 00345 HWND hParent) 00346 { 00347 RECT rc; 00348 BOOL Ret = FALSE; 00349 00350 infoPtr = HeapAlloc(GetProcessHeap(), 00351 0, 00352 sizeof(MAP)); 00353 if (infoPtr) 00354 { 00355 SetLastError(0); 00356 SetWindowLongPtrW(hwnd, 00357 0, 00358 (DWORD_PTR)infoPtr); 00359 if (GetLastError() == 0) 00360 { 00361 ZeroMemory(infoPtr, 00362 sizeof(MAP)); 00363 00364 infoPtr->hMapWnd = hwnd; 00365 infoPtr->hParent = hParent; 00366 00367 GetClientRect(hwnd, &rc); 00368 infoPtr->ClientSize.cx = rc.right; 00369 infoPtr->ClientSize.cy = rc.bottom; 00370 infoPtr->CellSize.cx = infoPtr->ClientSize.cx / XCELLS; 00371 infoPtr->CellSize.cy = infoPtr->ClientSize.cy / YCELLS; 00372 00373 infoPtr->pActiveCell = NULL; 00374 00375 SetGrid(infoPtr); 00376 00377 SetScrollRange(hwnd, SB_VERT, 0, 255, FALSE); 00378 SetScrollPos(hwnd, SB_VERT, 0, TRUE); 00379 00380 Ret = TRUE; 00381 } 00382 } 00383 00384 return Ret; 00385 } 00386 00387 00388 static 00389 VOID 00390 OnVScroll(PMAP infoPtr, 00391 INT Value, 00392 INT Pos) 00393 { 00394 INT iYDiff, iOldYStart = infoPtr->iYStart; 00395 00396 switch (Value) 00397 { 00398 case SB_LINEUP: 00399 infoPtr->iYStart -= 1; 00400 break; 00401 00402 case SB_LINEDOWN: 00403 infoPtr->iYStart += 1; 00404 break; 00405 00406 case SB_PAGEUP: 00407 infoPtr->iYStart -= YCELLS; 00408 break; 00409 00410 case SB_PAGEDOWN: 00411 infoPtr->iYStart += YCELLS; 00412 break; 00413 00414 case SB_THUMBTRACK: 00415 infoPtr->iYStart = Pos; 00416 break; 00417 00418 default: 00419 break; 00420 } 00421 00422 infoPtr->iYStart = max(0, 00423 min(infoPtr->iYStart, 255*16)); 00424 00425 iYDiff = iOldYStart - infoPtr->iYStart; 00426 if (iYDiff) 00427 { 00428 if (infoPtr->hLrgWnd != NULL) 00429 { 00430 ShowWindow(infoPtr->hLrgWnd, SW_HIDE); 00431 } 00432 00433 SetScrollPos(infoPtr->hMapWnd, 00434 SB_VERT, 00435 infoPtr->iYStart, 00436 TRUE); 00437 00438 if (abs(iYDiff) < YCELLS) 00439 { 00440 RECT rect; 00441 GetClientRect(infoPtr->hMapWnd, &rect); 00442 rect.top += 2; 00443 rect.bottom -= 2; 00444 ScrollWindowEx(infoPtr->hMapWnd, 00445 0, 00446 iYDiff * infoPtr->CellSize.cy, 00447 &rect, 00448 &rect, 00449 NULL, 00450 NULL, 00451 SW_INVALIDATE); 00452 } 00453 else 00454 { 00455 InvalidateRect(infoPtr->hMapWnd, 00456 NULL, 00457 TRUE); 00458 } 00459 00460 if (infoPtr->hLrgWnd != NULL) 00461 { 00462 ShowWindow(infoPtr->hLrgWnd, SW_SHOW); 00463 } 00464 } 00465 } 00466 00467 00468 static 00469 VOID 00470 OnPaint(PMAP infoPtr, 00471 WPARAM wParam) 00472 { 00473 PAINTSTRUCT ps; 00474 HDC hdc; 00475 00476 00477 if (wParam != 0) 00478 { 00479 if (!GetUpdateRect(infoPtr->hMapWnd, 00480 &ps.rcPaint, 00481 TRUE)) 00482 { 00483 return; 00484 } 00485 hdc = (HDC)wParam; 00486 } 00487 else 00488 { 00489 hdc = BeginPaint(infoPtr->hMapWnd, 00490 &ps); 00491 if (hdc == NULL) 00492 { 00493 return; 00494 } 00495 } 00496 00497 DrawGrid(infoPtr, &ps); 00498 00499 FillGrid(infoPtr, &ps); 00500 00501 if (wParam == 0) 00502 { 00503 EndPaint(infoPtr->hMapWnd, 00504 &ps); 00505 } 00506 } 00507 00508 00509 LRESULT 00510 CALLBACK 00511 MapWndProc(HWND hwnd, 00512 UINT uMsg, 00513 WPARAM wParam, 00514 LPARAM lParam) 00515 { 00516 PMAP infoPtr; 00517 LRESULT Ret = 0; 00518 00519 infoPtr = (PMAP)GetWindowLongPtrW(hwnd, 00520 0); 00521 00522 switch (uMsg) 00523 { 00524 case WM_CREATE: 00525 { 00526 if (!OnCreate(infoPtr, 00527 hwnd, 00528 ((LPCREATESTRUCTW)lParam)->hwndParent)) 00529 { 00530 return (LRESULT)-1; 00531 } 00532 00533 break; 00534 } 00535 00536 case WM_LBUTTONDOWN: 00537 { 00538 OnClick(infoPtr, 00539 LOWORD(lParam), 00540 HIWORD(lParam)); 00541 00542 break; 00543 } 00544 00545 case WM_LBUTTONDBLCLK: 00546 { 00547 NotifyParentOfSelection(infoPtr, 00548 FM_SETCHAR, 00549 infoPtr->pActiveCell->ch); 00550 00551 00552 break; 00553 } 00554 00555 case WM_VSCROLL: 00556 { 00557 OnVScroll(infoPtr, 00558 LOWORD(wParam), 00559 HIWORD(wParam)); 00560 00561 break; 00562 } 00563 00564 case FM_SETFONT: 00565 SetFont(infoPtr, (LPWSTR)lParam); 00566 break; 00567 00568 case FM_GETCHAR: 00569 { 00570 if (!infoPtr->pActiveCell) return 0; 00571 return infoPtr->pActiveCell->ch; 00572 } 00573 00574 case FM_GETHFONT: 00575 return (LRESULT)infoPtr->hFont; 00576 00577 case WM_PAINT: 00578 { 00579 OnPaint(infoPtr, 00580 wParam); 00581 break; 00582 } 00583 00584 case WM_DESTROY: 00585 { 00586 DeleteObject(infoPtr->hFont); 00587 HeapFree(GetProcessHeap(), 00588 0, 00589 infoPtr); 00590 SetWindowLongPtrW(hwnd, 00591 0, 00592 (DWORD_PTR)NULL); 00593 break; 00594 } 00595 00596 default: 00597 { 00598 Ret = DefWindowProcW(hwnd, 00599 uMsg, 00600 wParam, 00601 lParam); 00602 break; 00603 } 00604 } 00605 00606 return Ret; 00607 } 00608 00609 00610 BOOL 00611 RegisterMapClasses(HINSTANCE hInstance) 00612 { 00613 WNDCLASSW wc = {0}; 00614 00615 wc.style = CS_DBLCLKS; 00616 wc.lpfnWndProc = MapWndProc; 00617 wc.cbWndExtra = sizeof(PMAP); 00618 wc.hInstance = hInstance; 00619 wc.hCursor = LoadCursorW(NULL, 00620 (LPWSTR)IDC_ARROW); 00621 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 00622 wc.lpszClassName = szMapWndClass; 00623 00624 if (RegisterClassW(&wc)) 00625 { 00626 wc.lpfnWndProc = LrgCellWndProc; 00627 wc.cbWndExtra = 0; 00628 wc.lpszClassName = szLrgCellWndClass; 00629 00630 return RegisterClassW(&wc) != 0; 00631 } 00632 00633 return FALSE; 00634 } 00635 00636 VOID 00637 UnregisterMapClasses(HINSTANCE hInstance) 00638 { 00639 UnregisterClassW(szMapWndClass, 00640 hInstance); 00641 00642 UnregisterClassW(szLrgCellWndClass, 00643 hInstance); 00644 } Generated on Thu Feb 9 04:38:59 2012 for ReactOS by
1.6.3
|