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