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