1 /* 2 * PROJECT: ReactOS Magnify 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/applications/magnify/magnifier.c 5 * PURPOSE: Magnification of parts of the screen. 6 * AUTHORS: 7 * Marc Piulachs <marc.piulachs@codexchange.net> 8 * David Quintana <gigaherz@gmail.com> 9 */ 10 11 /* TODO: Support AppBar types other than ABE_TOP */ 12 13 #include "magnifier.h" 14 15 #include <winbase.h> 16 #include <winuser.h> 17 #include <wingdi.h> 18 #include <winnls.h> 19 #include <shellapi.h> 20 #include <windowsx.h> 21 #include <stdlib.h> 22 #include <tchar.h> 23 24 #include "resource.h" 25 26 #define APPMSG_NOTIFYICON (WM_APP+1) 27 #define APPMSG_APPBAR (WM_APP+2) 28 29 const TCHAR szWindowClass[] = TEXT("MAGNIFIER"); 30 31 /* Global Variables */ 32 HINSTANCE hInst; 33 HWND hMainWnd; 34 35 #define MAX_LOADSTRING 100 36 TCHAR szTitle[MAX_LOADSTRING]; 37 38 #define TIMER_SPEED 1 39 #define REPAINT_SPEED 100 40 41 DWORD lastTicks = 0; 42 43 HWND hDesktopWindow = NULL; 44 45 NOTIFYICONDATA nid; 46 HICON notifyIcon; 47 HMENU notifyMenu; 48 HWND hOptionsDialog; 49 BOOL bOptionsDialog = FALSE; 50 BOOL bRecreateOffscreenDC = TRUE; 51 LONG sourceWidth = 0; 52 LONG sourceHeight = 0; 53 HDC hdcOffscreen = NULL; 54 HBITMAP hbmpOffscreen = NULL; 55 HANDLE hbmpOld; 56 POINT ptDragOffset; 57 INT nearEdge; 58 59 /* Current magnified area */ 60 POINT cp; 61 62 /* Last positions */ 63 POINT pMouse; 64 POINT pCaret; 65 POINT pFocus; 66 HWND pCaretWnd; 67 HWND pFocusWnd; 68 69 ATOM MyRegisterClass(HINSTANCE hInstance); 70 BOOL InitInstance(HINSTANCE, int); 71 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 72 INT_PTR CALLBACK AboutProc(HWND, UINT, WPARAM, LPARAM); 73 INT_PTR CALLBACK OptionsProc(HWND, UINT, WPARAM, LPARAM); 74 INT_PTR CALLBACK WarningProc(HWND, UINT, WPARAM, LPARAM); 75 76 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 77 { 78 MSG msg; 79 HACCEL hAccelTable; 80 81 UNREFERENCED_PARAMETER(hPrevInstance); 82 UNREFERENCED_PARAMETER(lpCmdLine); 83 84 switch (GetUserDefaultUILanguage()) 85 { 86 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT): 87 SetProcessDefaultLayout(LAYOUT_RTL); 88 break; 89 90 default: 91 break; 92 } 93 94 /* Initialize global strings */ 95 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 96 MyRegisterClass(hInstance); 97 98 /* Perform application initialization */ 99 if (!InitInstance(hInstance, nCmdShow)) 100 return FALSE; 101 102 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MAGNIFIER)); 103 104 /* Main message loop */ 105 while (GetMessage(&msg, NULL, 0, 0)) 106 { 107 if (!TranslateAccelerator(hMainWnd, hAccelTable, &msg)) 108 { 109 TranslateMessage(&msg); 110 DispatchMessage(&msg); 111 } 112 } 113 114 115 SelectObject(hdcOffscreen, hbmpOld); 116 DeleteObject (hbmpOffscreen); 117 DeleteDC(hdcOffscreen); 118 119 return (int) msg.wParam; 120 } 121 122 ATOM MyRegisterClass(HINSTANCE hInstance) 123 { 124 WNDCLASS wc; 125 126 wc.style = CS_HREDRAW | CS_VREDRAW; 127 wc.lpfnWndProc = WndProc; 128 wc.cbClsExtra = 0; 129 wc.cbWndExtra = 0; 130 wc.hInstance = hInstance; 131 wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON)); 132 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 133 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 134 wc.lpszMenuName = NULL; //MAKEINTRESOURCE(IDC_MAGNIFIER); 135 wc.lpszClassName = szWindowClass; 136 137 return RegisterClass(&wc); 138 } 139 140 void DoAppBarStuff(DWORD mode) 141 { 142 UINT uState; 143 APPBARDATA data = {0}; 144 data.cbSize = sizeof(data); 145 data.hWnd = hMainWnd; 146 data.uCallbackMessage = APPMSG_APPBAR; 147 148 if (mode == ABM_NEW || mode == ABM_SETPOS) 149 { 150 HWND hWndOrder = HWND_BOTTOM; 151 int rcw, rch; 152 RECT rcWorkArea; 153 SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); 154 155 if(mode == ABM_NEW) 156 { 157 SHAppBarMessage(ABM_NEW, &data); 158 159 switch(AppBarConfig.uEdge) 160 { 161 case ABE_LEFT: 162 data.rc.top = rcWorkArea.top; 163 data.rc.bottom = rcWorkArea.bottom; 164 data.rc.left = rcWorkArea.left; 165 data.rc.right = data.rc.left + AppBarConfig.appBarSizes.left; 166 break; 167 case ABE_TOP: 168 data.rc.left = rcWorkArea.left; 169 data.rc.right = rcWorkArea.right; 170 data.rc.top = rcWorkArea.top; 171 data.rc.bottom = data.rc.top + AppBarConfig.appBarSizes.top; 172 break; 173 case ABE_RIGHT: 174 data.rc.top = rcWorkArea.top; 175 data.rc.bottom = rcWorkArea.bottom; 176 data.rc.right = rcWorkArea.left; 177 data.rc.left = data.rc.right - AppBarConfig.appBarSizes.right; 178 break; 179 case ABE_BOTTOM: 180 data.rc.left = rcWorkArea.left; 181 data.rc.right = rcWorkArea.right; 182 data.rc.bottom = rcWorkArea.bottom; 183 data.rc.top = data.rc.bottom - AppBarConfig.appBarSizes.bottom; 184 break; 185 } 186 } 187 else 188 { 189 GetWindowRect(hMainWnd, &data.rc); 190 } 191 192 data.uEdge = AppBarConfig.uEdge; 193 uState = SHAppBarMessage(ABM_QUERYPOS, &data); 194 195 uState = SHAppBarMessage(ABM_SETPOS, &data); 196 197 rcw = data.rc.right-data.rc.left; 198 rch = data.rc.bottom-data.rc.top; 199 200 uState = SHAppBarMessage(ABM_GETSTATE, &data); 201 if(uState & ABS_ALWAYSONTOP) 202 hWndOrder = HWND_TOPMOST; 203 204 SetWindowPos(hMainWnd, hWndOrder, data.rc.left, data.rc.top, rcw, rch, SWP_SHOWWINDOW|SWP_NOCOPYBITS); 205 206 } 207 else if(mode == ABM_GETSTATE) 208 { 209 HWND hWndOrder = HWND_BOTTOM; 210 uState = SHAppBarMessage(ABM_GETSTATE, &data); 211 if(uState & ABS_ALWAYSONTOP) 212 hWndOrder = HWND_TOPMOST; 213 SetWindowPos(hMainWnd, hWndOrder, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 214 } 215 else if(mode == ABM_ACTIVATE) 216 { 217 SHAppBarMessage(ABM_ACTIVATE, &data); 218 } 219 else if(mode == ABM_WINDOWPOSCHANGED) 220 { 221 SHAppBarMessage(ABM_WINDOWPOSCHANGED, &data); 222 } 223 else if(mode == ABM_REMOVE) 224 { 225 SHAppBarMessage(ABM_REMOVE, &data); 226 } 227 } 228 229 void AttachAppBar(INT uEdge) 230 { 231 if (AppBarConfig.uEdge == uEdge) 232 return; 233 234 if(AppBarConfig.uEdge < 0 && uEdge >= 0) 235 { 236 SetWindowLongPtr(hMainWnd, GWL_STYLE, GetWindowLongPtr(hMainWnd, GWL_STYLE) & (~WS_CAPTION)); 237 } 238 else if(uEdge < 0 && AppBarConfig.uEdge>=0) 239 { 240 SetWindowLongPtr(hMainWnd, GWL_STYLE, GetWindowLongPtr(hMainWnd, GWL_STYLE) | WS_CAPTION); 241 SetWindowPos(hMainWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED); 242 } 243 244 if(AppBarConfig.uEdge >= 0) 245 { 246 DoAppBarStuff(ABM_REMOVE); 247 } 248 249 if (uEdge >=0) 250 { 251 AppBarConfig.uEdge = uEdge; 252 DoAppBarStuff(ABM_NEW); 253 } 254 else 255 { 256 RECT rc = AppBarConfig.rcFloating; 257 SetWindowPos(hMainWnd, HWND_TOPMOST, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 0); 258 } 259 260 AppBarConfig.uEdge = uEdge; 261 } 262 263 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 264 { 265 RECT rc; 266 DWORD exStyles = WS_EX_TOOLWINDOW | WS_EX_CONTROLPARENT; 267 DWORD dwStyles = WS_SIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; 268 269 /* Load settings from registry */ 270 LoadSettings(); 271 272 rc = AppBarConfig.rcFloating; 273 274 hInst = hInstance; // Store instance handle in our global variable 275 276 if (AppBarConfig.uEdge<0) 277 { 278 dwStyles |= WS_CAPTION; 279 exStyles |= WS_EX_TOPMOST; 280 } 281 282 /* Create the Window */ 283 hMainWnd = CreateWindowEx( 284 exStyles, 285 szWindowClass, 286 szTitle, 287 dwStyles, 288 rc.left, 289 rc.top, 290 rc.right-rc.left, 291 rc.bottom-rc.top, 292 NULL, 293 NULL, 294 hInstance, 295 NULL); 296 297 if (!hMainWnd) 298 return FALSE; 299 300 if (AppBarConfig.uEdge>=0) DoAppBarStuff(ABM_NEW); 301 else SetWindowPos(hMainWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); 302 303 // In Windows 2003's Magnifier, the "Start Minimized" setting 304 // refers exclusively to the options dialog, not the main window itself. 305 hOptionsDialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOGOPTIONS), hMainWnd, OptionsProc); 306 if (bStartMinimized) 307 ShowWindow(hOptionsDialog, SW_HIDE); 308 else 309 ShowWindow(hOptionsDialog, SW_SHOW); 310 311 if (bShowWarning) 312 DialogBox(hInstance, MAKEINTRESOURCE(IDD_WARNINGDIALOG), hMainWnd, WarningProc); 313 314 return TRUE; 315 } 316 317 void Refresh() 318 { 319 if (!IsIconic(hMainWnd)) 320 { 321 /* Invalidate the client area forcing a WM_PAINT message */ 322 InvalidateRgn(hMainWnd, NULL, TRUE); 323 } 324 } 325 326 void GetBestOverlapWithMonitors(LPRECT rect) 327 { 328 int rcLeft, rcTop; 329 int rcWidth, rcHeight; 330 RECT rcMon; 331 HMONITOR hMon = MonitorFromRect(rect, MONITOR_DEFAULTTONEAREST); 332 MONITORINFO info; 333 info.cbSize = sizeof(info); 334 335 GetMonitorInfo(hMon, &info); 336 337 rcMon = info.rcMonitor; 338 339 rcLeft = rect->left; 340 rcTop = rect->top; 341 rcWidth = (rect->right - rect->left); 342 rcHeight = (rect->bottom - rect->top); 343 344 if (rcLeft < rcMon.left) 345 rcLeft = rcMon.left; 346 347 if (rcTop < rcMon.top) 348 rcTop = rcMon.top; 349 350 if (rcLeft > (rcMon.right - rcWidth)) 351 rcLeft = (rcMon.right - rcWidth); 352 353 if (rcTop > (rcMon.bottom - rcHeight)) 354 rcTop = (rcMon.bottom - rcHeight); 355 356 OffsetRect(rect, (rcLeft-rect->left), (rcTop-rect->top)); 357 } 358 359 void Draw(HDC aDc) 360 { 361 HDC desktopHdc = NULL; 362 363 RECT sourceRect, intersectedRect; 364 RECT targetRect, appRect; 365 DWORD rop = SRCCOPY; 366 CURSORINFO cinfo; 367 ICONINFO iinfo; 368 369 int AppWidth, AppHeight; 370 371 if (bInvertColors) 372 rop = NOTSRCCOPY; 373 374 desktopHdc = GetDC(0); 375 376 GetClientRect(hMainWnd, &appRect); 377 AppWidth = (appRect.right - appRect.left); 378 AppHeight = (appRect.bottom - appRect.top); 379 380 ZeroMemory(&cinfo, sizeof(cinfo)); 381 ZeroMemory(&iinfo, sizeof(iinfo)); 382 cinfo.cbSize = sizeof(cinfo); 383 GetCursorInfo(&cinfo); 384 GetIconInfo(cinfo.hCursor, &iinfo); 385 386 targetRect = appRect; 387 ClientToScreen(hMainWnd, (POINT*)&targetRect.left); 388 ClientToScreen(hMainWnd, (POINT*)&targetRect.right); 389 390 if (bRecreateOffscreenDC || !hdcOffscreen) 391 { 392 bRecreateOffscreenDC = FALSE; 393 394 if(hdcOffscreen) 395 { 396 SelectObject(hdcOffscreen, hbmpOld); 397 DeleteObject (hbmpOffscreen); 398 DeleteDC(hdcOffscreen); 399 } 400 401 sourceWidth = AppWidth / iZoom; 402 sourceHeight = AppHeight / iZoom; 403 404 /* Create a memory DC compatible with client area DC */ 405 hdcOffscreen = CreateCompatibleDC(desktopHdc); 406 407 /* Create a bitmap compatible with the client area DC */ 408 hbmpOffscreen = CreateCompatibleBitmap( 409 desktopHdc, 410 sourceWidth, 411 sourceHeight); 412 413 /* Select our bitmap in memory DC and save the old one */ 414 hbmpOld = SelectObject(hdcOffscreen , hbmpOffscreen); 415 } 416 417 GetWindowRect(hDesktopWindow, &sourceRect); 418 sourceRect.left = (cp.x) - (sourceWidth /2); 419 sourceRect.top = (cp.y) - (sourceHeight /2); 420 sourceRect.right = sourceRect.left + sourceWidth; 421 sourceRect.bottom = sourceRect.top + sourceHeight; 422 423 GetBestOverlapWithMonitors(&sourceRect); 424 425 /* Paint the screen bitmap to our in memory DC */ 426 BitBlt( 427 hdcOffscreen, 428 0, 429 0, 430 sourceWidth, 431 sourceHeight, 432 desktopHdc, 433 sourceRect.left, 434 sourceRect.top, 435 rop); 436 437 if (IntersectRect(&intersectedRect, &sourceRect, &targetRect)) 438 { 439 OffsetRect(&intersectedRect, -sourceRect.left, -sourceRect.top); 440 FillRect(hdcOffscreen, &intersectedRect, GetStockObject(DC_BRUSH)); 441 } 442 443 /* Draw the mouse pointer in the right position */ 444 DrawIcon( 445 hdcOffscreen , 446 pMouse.x - iinfo.xHotspot - sourceRect.left, // - 10, 447 pMouse.y - iinfo.yHotspot - sourceRect.top, // - 10, 448 cinfo.hCursor); 449 450 /* Blast the stretched image from memory DC to window DC */ 451 StretchBlt( 452 aDc, 453 0, 454 0, 455 AppWidth, 456 AppHeight, 457 hdcOffscreen, 458 0, 459 0, 460 sourceWidth, 461 sourceHeight, 462 SRCCOPY | NOMIRRORBITMAP); 463 464 /* Cleanup */ 465 if (iinfo.hbmMask) 466 DeleteObject(iinfo.hbmMask); 467 if (iinfo.hbmColor) 468 DeleteObject(iinfo.hbmColor); 469 ReleaseDC(hDesktopWindow, desktopHdc); 470 } 471 472 void HandleNotifyIconMessage(HWND hWnd, WPARAM wParam, LPARAM lParam) 473 { 474 POINT pt; 475 476 switch(lParam) 477 { 478 case WM_LBUTTONUP: 479 PostMessage(hMainWnd, WM_COMMAND, IDM_OPTIONS, 0); 480 break; 481 case WM_RBUTTONUP: 482 GetCursorPos (&pt); 483 TrackPopupMenu(notifyMenu, 0, pt.x, pt.y, 0, hWnd, NULL); 484 break; 485 } 486 } 487 488 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 489 { 490 int wmId; 491 492 switch (message) 493 { 494 case WM_TIMER: 495 { 496 BOOL hasMoved = FALSE; 497 498 GUITHREADINFO guiInfo; 499 guiInfo.cbSize = sizeof(guiInfo); 500 501 GetGUIThreadInfo(0, &guiInfo); 502 503 if (bFollowMouse) 504 { 505 POINT pNewMouse; 506 507 //Get current mouse position 508 GetCursorPos (&pNewMouse); 509 510 #define PointsAreEqual(pt1, pt2) (((pt1).x == (pt2).x) && ((pt1).y == (pt2).y)) 511 512 //If mouse has moved ... 513 if (!PointsAreEqual(pMouse, pNewMouse)) 514 { 515 //Update to new position 516 pMouse = pNewMouse; 517 cp = pNewMouse; 518 hasMoved = TRUE; 519 } 520 } 521 522 if(guiInfo.hwndActive != hMainWnd) 523 { 524 if (bFollowCaret) 525 { 526 if (guiInfo.hwndCaret) 527 { 528 POINT ptCaret; 529 ptCaret.x = (guiInfo.rcCaret.left + guiInfo.rcCaret.right) / 2; 530 ptCaret.y = (guiInfo.rcCaret.top + guiInfo.rcCaret.bottom) / 2; 531 532 if ((pCaretWnd != guiInfo.hwndCaret) || !PointsAreEqual(pCaret, ptCaret)) 533 { 534 //Update to new position 535 pCaret = ptCaret; 536 pCaretWnd = guiInfo.hwndCaret; 537 if(!hasMoved) 538 { 539 ClientToScreen (guiInfo.hwndCaret, (LPPOINT) &ptCaret); 540 cp = ptCaret; 541 hasMoved = TRUE; 542 } 543 } 544 } 545 else 546 { 547 pCaretWnd = NULL; 548 } 549 } 550 551 if (bFollowFocus) 552 { 553 if(guiInfo.hwndFocus && !guiInfo.hwndCaret) 554 { 555 POINT ptFocus; 556 RECT activeRect; 557 558 //Get current control focus 559 GetWindowRect(guiInfo.hwndFocus, &activeRect); 560 ptFocus.x = (activeRect.left + activeRect.right) / 2; 561 ptFocus.y = (activeRect.top + activeRect.bottom) / 2; 562 563 if((guiInfo.hwndFocus != pFocusWnd) || !PointsAreEqual(pFocus, ptFocus)) 564 { 565 //Update to new position 566 pFocus = ptFocus; 567 pFocusWnd = guiInfo.hwndFocus; 568 if(!hasMoved) 569 { 570 cp = ptFocus; 571 hasMoved = TRUE; 572 } 573 } 574 } 575 else 576 { 577 pFocusWnd = NULL; 578 } 579 } 580 } 581 582 if(!hasMoved) 583 { 584 DWORD newTicks = GetTickCount(); 585 DWORD elapsed = (newTicks - lastTicks); 586 if(elapsed > REPAINT_SPEED) 587 { 588 hasMoved = TRUE; 589 } 590 } 591 592 if(hasMoved) 593 { 594 lastTicks = GetTickCount(); 595 Refresh(); 596 } 597 598 return 0; 599 } 600 601 case WM_COMMAND: 602 { 603 wmId = LOWORD(wParam); 604 /* Parse the menu selections */ 605 switch (wmId) 606 { 607 case IDM_OPTIONS: 608 if(bOptionsDialog) 609 { 610 ShowWindow(hOptionsDialog, SW_HIDE); 611 } 612 else 613 { 614 ShowWindow(hOptionsDialog, SW_SHOW); 615 } 616 break; 617 case IDM_ABOUT: 618 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutProc); 619 break; 620 case IDM_EXIT: 621 DestroyWindow(hWnd); 622 break; 623 default: 624 return DefWindowProc(hWnd, message, wParam, lParam); 625 } 626 return 0; 627 } 628 629 case WM_PAINT: 630 { 631 PAINTSTRUCT PaintStruct; 632 HDC dc; 633 dc = BeginPaint(hWnd, &PaintStruct); 634 Draw(dc); 635 EndPaint(hWnd, &PaintStruct); 636 return 0; 637 } 638 639 case WM_CONTEXTMENU: 640 TrackPopupMenu(notifyMenu, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), 0, hWnd, NULL); 641 return 0; 642 643 case WM_LBUTTONDOWN: 644 { 645 RECT rc; 646 POINT pt; 647 SetCapture(hWnd); 648 649 GetCursorPos(&pt); 650 GetWindowRect(hWnd, &rc); 651 ptDragOffset.x = pt.x - rc.left; 652 ptDragOffset.y = pt.y - rc.top; 653 654 nearEdge = AppBarConfig.uEdge; 655 656 break; 657 } 658 case WM_MOUSEMOVE: 659 if(GetCapture() == hWnd) 660 { 661 RECT rc; 662 POINT pt; 663 RECT rcWorkArea; 664 SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); 665 GetCursorPos(&pt); 666 GetWindowRect(hWnd, &rc); 667 668 if(AppBarConfig.uEdge>=0) 669 { 670 if (pt.x >= rcWorkArea.left && pt.x <= rcWorkArea.right && 671 pt.y >= rcWorkArea.top && pt.y <= rcWorkArea.bottom) 672 { 673 AttachAppBar(-2); 674 675 // Fixup offset 676 GetWindowRect(hWnd, &rc); 677 ptDragOffset.x = (rc.right-rc.left)/2; 678 ptDragOffset.y = 2; 679 680 rc.left = pt.x - ptDragOffset.x; 681 rc.top = pt.y - ptDragOffset.y; 682 683 SetWindowPos(hWnd, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE); 684 } 685 } 686 else 687 { 688 if(pt.x <= rcWorkArea.left+8 && nearEdge != ABE_LEFT) 689 { 690 AttachAppBar(ABE_LEFT); 691 nearEdge = ABE_LEFT; 692 } 693 else if(pt.y <= rcWorkArea.top+8 && nearEdge != ABE_TOP) 694 { 695 AttachAppBar(ABE_TOP); 696 nearEdge = ABE_TOP; 697 } 698 else if(pt.x >= rcWorkArea.right-8 && nearEdge != ABE_RIGHT) 699 { 700 AttachAppBar(ABE_RIGHT); 701 nearEdge = ABE_RIGHT; 702 } 703 else if(pt.y >= rcWorkArea.bottom-8 && nearEdge != ABE_BOTTOM) 704 { 705 AttachAppBar(ABE_BOTTOM); 706 nearEdge = ABE_BOTTOM; 707 } 708 else 709 { 710 rc.left = pt.x - ptDragOffset.x; 711 rc.top = pt.y - ptDragOffset.y; 712 713 SetWindowPos(hWnd, HWND_TOPMOST, rc.left, rc.top, 0, 0, SWP_NOSIZE); 714 nearEdge = -1; 715 } 716 } 717 718 pMouse = pt; 719 Refresh(); 720 } 721 break; 722 case WM_LBUTTONUP: 723 if(GetCapture() == hWnd) 724 { 725 if (AppBarConfig.uEdge>=0) 726 DoAppBarStuff(ABM_GETSTATE); 727 else 728 SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 729 ReleaseCapture(); 730 } 731 break; 732 733 case WM_SIZE: 734 if(AppBarConfig.uEdge>=0) DoAppBarStuff(ABM_SETPOS); 735 /* fallthrough */ 736 case WM_DISPLAYCHANGE: 737 bRecreateOffscreenDC = TRUE; 738 Refresh(); 739 break; 740 741 case WM_ERASEBKGND: 742 // handle WM_ERASEBKGND by simply returning non-zero because we did all the drawing in WM_PAINT. 743 return 0; 744 745 case WM_DESTROY: 746 { 747 if (AppBarConfig.uEdge >= 0) 748 DoAppBarStuff(ABM_REMOVE); 749 750 KillTimer(hWnd, 1); 751 752 /* Save settings to registry */ 753 SaveSettings(); 754 755 /* Cleanup notification icon */ 756 ZeroMemory(&nid, sizeof(nid)); 757 nid.cbSize = sizeof(nid); 758 nid.uFlags = NIF_MESSAGE; 759 nid.hWnd = hWnd; 760 nid.uCallbackMessage = APPMSG_NOTIFYICON; 761 Shell_NotifyIcon(NIM_DELETE, &nid); 762 DestroyIcon(notifyIcon); 763 764 DestroyWindow(hOptionsDialog); 765 766 PostQuitMessage(0); 767 return 0; 768 } 769 770 case WM_CREATE: 771 { 772 HMENU tempMenu; 773 774 /* Get the desktop window */ 775 hDesktopWindow = GetDesktopWindow(); 776 777 /* Set the timer */ 778 SetTimer(hWnd, 1, TIMER_SPEED, NULL); 779 780 /* Notification icon */ 781 notifyIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, 0); 782 783 ZeroMemory(&nid, sizeof(nid)); 784 nid.cbSize = sizeof(nid); 785 nid.uFlags = NIF_ICON | NIF_MESSAGE; 786 nid.hWnd = hWnd; 787 nid.uCallbackMessage = APPMSG_NOTIFYICON; 788 nid.hIcon = notifyIcon; 789 Shell_NotifyIcon(NIM_ADD, &nid); 790 791 tempMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDC_MAGNIFIER)); 792 notifyMenu = GetSubMenu(tempMenu, 0); 793 RemoveMenu(tempMenu, 0, MF_BYPOSITION); 794 DestroyMenu(tempMenu); 795 return 0; 796 } 797 798 case APPMSG_APPBAR: 799 { 800 switch (wParam) 801 { 802 case ABN_STATECHANGE: 803 DoAppBarStuff(ABM_GETSTATE); 804 break; 805 case ABN_POSCHANGED: 806 DoAppBarStuff(ABM_SETPOS); 807 break; 808 case ABN_FULLSCREENAPP: 809 { 810 if(!lParam) 811 { 812 DoAppBarStuff(ABM_GETSTATE); 813 break; 814 } 815 816 SetWindowPos(hMainWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 817 break; 818 } 819 case ABN_WINDOWARRANGE: 820 if(lParam) 821 ShowWindow(hMainWnd, SW_HIDE); 822 else 823 ShowWindow(hMainWnd, SW_SHOW); 824 break; 825 } 826 return 0; 827 } 828 829 case APPMSG_NOTIFYICON: 830 HandleNotifyIconMessage(hWnd, wParam, lParam); 831 return 0; 832 833 case WM_ACTIVATE: 834 if(AppBarConfig.uEdge>=0) DoAppBarStuff(ABM_ACTIVATE); 835 break; 836 837 case WM_WINDOWPOSCHANGED: 838 if(AppBarConfig.uEdge>=0) DoAppBarStuff(ABM_WINDOWPOSCHANGED); 839 Refresh(); 840 break; 841 842 default: 843 break; 844 } 845 846 return DefWindowProc(hWnd, message, wParam, lParam); 847 } 848 849 INT_PTR CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 850 { 851 UNREFERENCED_PARAMETER(lParam); 852 switch (message) 853 { 854 case WM_INITDIALOG: 855 return (INT_PTR)TRUE; 856 857 case WM_COMMAND: 858 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 859 { 860 EndDialog(hDlg, LOWORD(wParam)); 861 return (INT_PTR)TRUE; 862 } 863 break; 864 } 865 866 return (INT_PTR)FALSE; 867 } 868 869 INT_PTR CALLBACK OptionsProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 870 { 871 UNREFERENCED_PARAMETER(lParam); 872 switch (message) 873 { 874 case WM_SHOWWINDOW: 875 bOptionsDialog = wParam; 876 break; 877 case WM_INITDIALOG: 878 { 879 // Add the zoom items... 880 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("1")); 881 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("2")); 882 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("3")); 883 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("4")); 884 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("5")); 885 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("6")); 886 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("7")); 887 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_ADDSTRING, 0, (LPARAM)("8")); 888 889 SendDlgItemMessage(hDlg, IDC_ZOOM, CB_SETCURSEL, iZoom - 1, 0); 890 891 if (bFollowMouse) 892 SendDlgItemMessage(hDlg,IDC_FOLLOWMOUSECHECK,BM_SETCHECK , wParam ,0); 893 894 if (bFollowFocus) 895 SendDlgItemMessage(hDlg,IDC_FOLLOWKEYBOARDCHECK,BM_SETCHECK , wParam ,0); 896 897 if (bFollowCaret) 898 SendDlgItemMessage(hDlg,IDC_FOLLOWTEXTEDITINGCHECK,BM_SETCHECK , wParam ,0); 899 900 if (bInvertColors) 901 SendDlgItemMessage(hDlg,IDC_INVERTCOLORSCHECK,BM_SETCHECK , wParam ,0); 902 903 if (bStartMinimized) 904 SendDlgItemMessage(hDlg,IDC_STARTMINIMIZEDCHECK,BM_SETCHECK , wParam ,0); 905 906 if (bShowMagnifier) 907 SendDlgItemMessage(hDlg,IDC_SHOWMAGNIFIERCHECK,BM_SETCHECK , wParam ,0); 908 909 return (INT_PTR)TRUE; 910 } 911 912 case WM_COMMAND: 913 switch (LOWORD(wParam)) 914 { 915 case IDOK: 916 case IDCANCEL: 917 ShowWindow(hDlg, SW_HIDE); 918 return (INT_PTR)TRUE; 919 920 case IDC_BUTTON_HELP: 921 /* Unimplemented */ 922 MessageBox(hDlg , TEXT("Magnifier help not available yet!") , TEXT("Help") , MB_OK); 923 break; 924 case IDC_ZOOM: 925 if (HIWORD(wParam) == CBN_SELCHANGE) 926 { 927 HWND hCombo = GetDlgItem(hDlg,IDC_ZOOM); 928 LPCTSTR currentZoomValue = TEXT(""); 929 930 /* Get index of current selection and the text of that selection */ 931 int currentSelectionIndex = ComboBox_GetCurSel(hCombo); 932 ComboBox_GetLBText(hCombo, currentSelectionIndex, currentZoomValue); 933 iZoom = _ttoi(currentZoomValue); 934 935 /* Trigger the Draw function to rezoom (which will be set false automatically after rezooming) */ 936 bRecreateOffscreenDC = TRUE; 937 938 /* Update the magnifier UI */ 939 Refresh(); 940 } 941 break; 942 case IDC_INVERTCOLORSCHECK: 943 bInvertColors = IsDlgButtonChecked(hDlg, IDC_INVERTCOLORSCHECK); 944 Refresh(); 945 break; 946 case IDC_FOLLOWMOUSECHECK: 947 bFollowMouse = IsDlgButtonChecked(hDlg, IDC_FOLLOWMOUSECHECK); 948 break; 949 case IDC_FOLLOWKEYBOARDCHECK: 950 bFollowFocus = IsDlgButtonChecked(hDlg, IDC_FOLLOWKEYBOARDCHECK); 951 break; 952 case IDC_FOLLOWTEXTEDITINGCHECK: 953 bFollowCaret = IsDlgButtonChecked(hDlg, IDC_FOLLOWTEXTEDITINGCHECK); 954 break; 955 case IDC_STARTMINIMIZEDCHECK: 956 bStartMinimized = IsDlgButtonChecked(hDlg, IDC_STARTMINIMIZEDCHECK); 957 break; 958 case IDC_SHOWMAGNIFIER: 959 bShowMagnifier = IsDlgButtonChecked(hDlg, IDC_SHOWMAGNIFIERCHECK); 960 if (bShowMagnifier) 961 ShowWindow (hMainWnd , SW_SHOW); 962 else 963 ShowWindow (hMainWnd , SW_HIDE); 964 break; 965 } 966 } 967 968 return (INT_PTR)FALSE; 969 } 970 971 INT_PTR CALLBACK WarningProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 972 { 973 UNREFERENCED_PARAMETER(lParam); 974 975 switch (message) 976 { 977 case WM_INITDIALOG: 978 return (INT_PTR)TRUE; 979 980 case WM_COMMAND: 981 switch (LOWORD(wParam)) 982 { 983 case IDC_SHOWWARNINGCHECK: 984 bShowWarning = !IsDlgButtonChecked(hDlg, IDC_SHOWWARNINGCHECK); 985 break; 986 } 987 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 988 { 989 EndDialog(hDlg, LOWORD(wParam)); 990 return (INT_PTR)TRUE; 991 } 992 break; 993 } 994 995 return (INT_PTR)FALSE; 996 } 997