Advertisement
Lorenzo501

Outlook Ad Overlay Btn (discontinued, was meant for Time Saver).ahk

Jun 20th, 2025 (edited)
670
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #Requires AutoHotkey 2.0
  2. /*
  3. [easiest way to have it always look basically fine by hiding the ad entirely unless tooltips are shown in certain areas, but remember that some Outlook tooltips have multiple lines of text
  4. and the search bar needs to hide the overlays and btn entirely, by detecting when the user has clicked inside the input field]
  5. |
  6. [make an algorithm that goes over every Outlook tooltip pixel of the mentioned row until there is no Outlook tooltip pixel found, then I know exactly how big the Outlook tooltip is and then
  7. I can simply have two rectangles resized so that it leaves a gap between them for the Outlook tooltip. but if the Outlook tooltip starts at the first overlay row pixel then I only need to
  8. have one rectangle, at the right side, being resized to leave a gap on the left side for the Outlook tooltip, and vice versa if the tooltip is at the last overlay row pixel, then I only
  9. need to have one rectangle, at the left side, being resized to leave a gap on the right side for the Outlook tooltip. these amounts of rectangles are about only one side of the ad section,
  10. top/bottom, so one/two rectangles above and one/two rectangles below. checking both top and bottom, to change either side or both as needed]
  11. |
  12. I can make rectangle GUIs (perhaps even using programmatically generated gradients) and then when the cursor hovers the bar directly above or below the ad section, which contains buttons.
  13. then I can detect if any pixels one row below the bar that's above the ad section have changed color, and if any pixels one row above the bar that's below the ad section have changed color.
  14. in which case I can temporarily hide the GUIs that are showing Outlook tooltips, until the cursor no longer hovers the bars. using my PointerDeviceHook w/ Move
  15. */
  16. F1::Reload()
  17. A_WinDelay := -1
  18. A_CoordModePixel := "Screen" ; For the LButton hotkey variant feature that skips inbox resize line clicks and for HandleActivatedWindowOutlookEvent
  19. A_CoordModeMouse := "Screen" ; For the LButton hotkey variant feature that skips inbox resize line clicks
  20.  
  21. EVENT_SYSTEM_FOREGROUND := 0x0003
  22. EVENT_SYSTEM_MINIMIZEEND := 0x0017
  23. HookEvent(EVENT_SYSTEM_FOREGROUND, HandleActivatedWindowOutlookEvent)
  24. HookEvent(EVENT_SYSTEM_MINIMIZEEND, HandleActivatedWindowOutlookEvent)
  25. customOutlookRefreshButtonMouseEventHook := PointerDeviceHook("Move", HandleCustomOutlookRefreshButtonMouseEvent, true)
  26.  
  27.     HandleActivatedWindowOutlookEvent(hWinEventHook, event, hWnd, *)
  28.     {
  29.         static isManagingCustomOutlookRefreshButton := false ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; not up-to-date, so how about renaming to isManagingCustomOutlookOverlays
  30.  
  31.         if (WinActive("E-mail ahk_class Olk Host"))
  32.         {
  33.             if (!isManagingCustomOutlookRefreshButton)
  34.             {
  35.                 isManagingCustomOutlookRefreshButton := true
  36.  
  37.                 ; Loading custom refresh btn for New Outlook or else merely making it always-on-top if it's already loaded
  38.                 if (!IsSet(adButtonOverlayedRefreshButtonGui))
  39.                 {
  40.                     Sleep(10) ; This is necessary to make WinGetClientPos retrieve the restored position
  41.                     WinGetClientPos(&outlookX, &outlookY,, &outlookHeight)
  42.  
  43. while (PixelGetColor(outlookX + 619, outlookY + 146) != 0xFFFFFF) ; Random white [Adv] pixel
  44.     continue ; NEEDS TIMEOUT AND GOTTA CHECK TOP LEFT CORNER WHITE PIXEL + BOTTOM RIGHT CORNER WHITE PIXEL (not one random white pixel)
  45.  
  46.                     global mobileAppButtonOverlayedRemoverGui := Gui("-Caption")
  47.                     mobileAppButtonOverlayedRemoverGui.BackColor := "Black" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"141414"
  48.                     WinSetExStyle("+0x08000000L", mobileAppButtonOverlayedRemoverGui) ; Adds WS_EX_NOACTIVATE
  49.                     mobileAppButtonOverlayedRemoverGui.Show("x" outlookX + 55 " y" outlookY + outlookHeight - 70 " w295 h65 NoActivate")
  50.                     GroupAdd("CustomOutlookNonClickableOverlays", "ahk_id " mobileAppButtonOverlayedRemoverGui.Hwnd) ;;;;;;;;;;;;;;;;;;;; remove from group before closing the wnd
  51.  
  52.                     global adButtonOverlayedBgGui := Gui("-Caption") ;;;;;;;;;;;;;;;;;;;; +AlwaysOnTop -Caption
  53.                     adButtonOverlayedBgGui.BackColor := "Black"
  54.                     WinSetTransparent(1, adButtonOverlayedBgGui)
  55.                     WinSetExStyle("+0x08000000L", adButtonOverlayedBgGui) ; Adds WS_EX_NOACTIVATE
  56.                     adButtonOverlayedBgGui.Show("x" outlookX + 358 " y" outlookY + 132 " w375 h81 NoActivate")
  57.                     GroupAdd("CustomOutlookNonClickableOverlays", "ahk_id " adButtonOverlayedBgGui.Hwnd) ;;;;;;;;;;;;;;;;;;;; remove from group before closing the wnd
  58.  
  59.                     global adButtonOverlayedInnerBgGui := Gui("-Caption") ;;;;;;;;;;;;;;;;;;;; +AlwaysOnTop -Caption
  60.                     adButtonOverlayedInnerBgGui.BackColor := "White" ;292929"
  61. ;WinSetTransparent(200, adButtonOverlayedInnerBgGui) ;REMOVE WHEN DONE
  62.                     WinSetExStyle("+0x08000000L", adButtonOverlayedInnerBgGui) ; Adds WS_EX_NOACTIVATE
  63.                     WinSetExStyle("+0x20", adButtonOverlayedInnerBgGui) ; Adds WS_EX_TRANSPARENT to let clicks pass-through
  64.                     adButtonOverlayedInnerBgGui.Show("x" outlookX + 368 " y" outlookY + 142 " w354 h66 NoActivate")
  65.  
  66.                     global adButtonOverlayedRefreshButtonBgGui := Gui("-Caption") ;;;;;;;;;;;;;;;;;;;; +AlwaysOnTop -Caption
  67.                     adButtonOverlayedRefreshButtonBgGui.BackColor := "292929"
  68.                     WinSetExStyle("+0x08000000L", adButtonOverlayedRefreshButtonBgGui) ; Adds WS_EX_NOACTIVATE
  69.                     WinSetExStyle("+0x20", adButtonOverlayedRefreshButtonBgGui) ; Adds WS_EX_TRANSPARENT to let clicks pass-through
  70.                     adButtonOverlayedRefreshButtonBgGui.Show("x" outlookX + 395 " y" outlookY + 157 " w300 h37 NoActivate")
  71.  
  72.                     global adButtonOverlayedRefreshButtonGui := Gui("-Caption") ;;;;;;;;;;;;;;;;;;;; +AlwaysOnTop -Caption
  73.                     adButtonOverlayedRefreshButtonGui.SetFont("s13", "Calibri")
  74.                     adButtonOverlayedRefreshButtonGui.AddButton("x0 y0 w300", "Refresh e-mails").OnEvent("Click", (*) => FocusHiddenButton())
  75.                     hiddenButton := adButtonOverlayedRefreshButtonGui.AddButton("-Tabstop y-100")
  76. ;..Gui.AddText("x0 y0 w50 h50 BackgroundFF00FF");can hide parts w/ multiple of these with WinSetTransColor for all non-Button GUIs, but it's better to repeat a region algorithm
  77.                     WinSetExStyle("+0x08000000L", adButtonOverlayedRefreshButtonGui) ; Adds WS_EX_NOACTIVATE
  78.                     WinSetTransparent(175, adButtonOverlayedRefreshButtonGui)
  79.                     adButtonOverlayedRefreshButtonGui.Show("x" outlookX + 395 " y" outlookY + 157 " w300 h37 NoActivate")
  80. ;ToolTip("LOADED")
  81.                     customOutlookRefreshButtonMouseEventHook.Start()
  82.                 }
  83.                 else
  84.                 {
  85. ;Sleep(10)
  86.                     mobileAppButtonOverlayedRemoverGui.Opt("+AlwaysOnTop")
  87.                     mobileAppButtonOverlayedRemoverGui.Opt("-AlwaysOnTop")
  88.                     adButtonOverlayedBgGui.Opt("+AlwaysOnTop")
  89.                     adButtonOverlayedBgGui.Opt("-AlwaysOnTop")
  90.                     adButtonOverlayedInnerBgGui.Opt("+AlwaysOnTop")
  91.                     adButtonOverlayedInnerBgGui.Opt("-AlwaysOnTop")
  92.                     adButtonOverlayedRefreshButtonBgGui.Opt("+AlwaysOnTop")
  93.                     adButtonOverlayedRefreshButtonBgGui.Opt("-AlwaysOnTop")
  94.                     adButtonOverlayedRefreshButtonGui.Opt("+AlwaysOnTop")
  95.                     adButtonOverlayedRefreshButtonGui.Opt("-AlwaysOnTop")
  96. ;ToolTip("NO LONGER OVERLAPPED")
  97.                 }
  98.  
  99.                 isManagingCustomOutlookRefreshButton := false
  100.             }
  101.         }
  102.         else if (IsSet(adButtonOverlayedRefreshButtonGui) && !WinExist(A_ScriptName " ahk_class AutoHotkeyGUI ahk_id " hWnd) && !isManagingCustomOutlookRefreshButton)
  103.         {
  104.             isManagingCustomOutlookRefreshButton := true
  105.  
  106.             if (WinGetMinMax("E-mail ahk_class Olk Host") = -1) ; Detects minimized wnd (Outlook is no longer being used)
  107.             {
  108.                 customOutlookRefreshButtonMouseEventHook.Stop()
  109.                 WinClose(mobileAppButtonOverlayedRemoverGui)
  110.                 WinClose(adButtonOverlayedBgGui)
  111.                 WinClose(adButtonOverlayedInnerBgGui)
  112.                 WinClose(adButtonOverlayedRefreshButtonBgGui)
  113.                 WinClose(adButtonOverlayedRefreshButtonGui)
  114.                 global adButtonOverlayedRefreshButtonGui := unset
  115. ;ToolTip("CLOSED")
  116.             }
  117.  
  118.             isManagingCustomOutlookRefreshButton := false
  119.         }
  120.  
  121.         FocusHiddenButton() => PostMessage(0x0028, hiddenButton.Hwnd, true) ; 0x0028 = WM_NEXTDLGCTL
  122.     }
  123.  
  124. HookEvent(event, fnObj, pid := 0) => DllCall("SetWinEventHook", "UInt", event, "UInt", event, "Ptr", 0, "Ptr", CallbackCreate(fnObj), "UInt", pid, "UInt", 0, "UInt", 0)
  125.  
  126. HandleCustomOutlookRefreshButtonMouseEvent(eventInfo)
  127. {
  128.     ;THESE SPLIT GUI(S) HAVE NOT BEEN MADE YET, SO IT'S TEMPORARILY USING THE OLD ONE. CAN REPLACE THE TWO UNCOMMENTED LINES WITH THE TWO COMMENTED LINES, ONCE THE GUI HAS BEEN SPLIT
  129. ;    topLeftAdButtonOverlayedInnerBgGui.GetClientPos(&topLeftAdButtonOverlayedInnerBgGuiX, &topLeftAdButtonOverlayedInnerBgGuiY)
  130. ;    bottomLeftAdButtonOverlayedInnerBgGui.GetClientPos(, &bottomLeftAdButtonOverlayedInnerBgGuiY,, &bottomLeftAdButtonOverlayedInnerBgGuiHeight)
  131. adButtonOverlayedInnerBgGui.GetClientPos(&topLeftAdButtonOverlayedInnerBgGuiX, &topLeftAdButtonOverlayedInnerBgGuiY)
  132. adButtonOverlayedInnerBgGui.GetClientPos(, &bottomLeftAdButtonOverlayedInnerBgGuiY,, &bottomLeftAdButtonOverlayedInnerBgGuiHeight) ;NOT SURE IF THIS IS NECESSARY ANYMORE, SEE IF USED LATER
  133.  
  134.     if (eventInfo.Pt.Y >= topLeftAdButtonOverlayedInnerBgGuiY - 54 && eventInfo.Pt.Y <= topLeftAdButtonOverlayedInnerBgGuiY - 23) ; Detects cursor on menubar directly above inbox
  135.     {
  136. ;hasFoundOutlookToolTipAtBottomLeftOfAd := false
  137. startTime := A_TickCount
  138.  
  139.         loop
  140.         {
  141.             if (hasFoundOutlookToolTipAtTopLeftOfAd := PixelGetColor(topLeftAdButtonOverlayedInnerBgGuiX, topLeftAdButtonOverlayedInnerBgGuiY - 1) != 0x292929)
  142.             {
  143.                 ;[I DON'T THINK I NEED THIS AFTER ALL, MAKES IT TAKE EVEN LONGER AND THEN I'D HAVE TO INCREASE THE TIMEOUT.. IS LIKELY MUCH FASTER TO SIMPLY ALWAYS SET BOTTOM WIDTH AS WELL]
  144.                 ;hasFoundOutlookToolTipAtBottomLeftOfAd := PixelGetColor(topLeftAdButtonOverlayedInnerBgGuiX
  145.                 ;    , bottomLeftAdButtonOverlayedInnerBgGuiY + bottomLeftAdButtonOverlayedInnerBgGuiHeight) != 0x292929
  146.  
  147.                 break
  148.             }
  149.  
  150.             ; Timeout for when the tooltip should have faded-in if there was one
  151.             if (A_TickCount - startTime > 300)
  152.             {
  153. ToolTip("[TIMEOUT] ON TOP BTN BAR!!!! " eventInfo.Pt.Y "`nhasFoundOutlookToolTipAtTopLeftOfAd: " hasFoundOutlookToolTipAtTopLeftOfAd) ;"`nhasFoundOutlookToolTipAtBottomLeftOfAd: "
  154.     ;hasFoundOutlookToolTipAtBottomLeftOfAd) ; BOTH BOOLS ALWAYS FALSE
  155.  
  156.                 return
  157.             }
  158.  
  159.             Sleep(10)
  160.         }
  161. ;
  162. ToolTip("ON TOP BTN BAR!!!! " eventInfo.Pt.Y "`nhasFoundOutlookToolTipAtTopLeftOfAd: " hasFoundOutlookToolTipAtTopLeftOfAd) ;"`nhasFoundOutlookToolTipAtBottomLeftOfAd: "
  163.     ;hasFoundOutlookToolTipAtBottomLeftOfAd) ; FIRST BOOL ALWAYS TRUE
  164.  
  165. ;[COULD PROBABLY DO IT THE WAY I INITIALLY PLANNED BUT THEN IT ONLY WORKS FOR HOW MY OWN OUTLOOK CURRENTLY IS ORGANIZED, THE BUTTONS AND THEIR TOOLTIPS.. THE NEW SOLUTION THE LINE BELOW
  166. ;THIS ONE IS ALSO NOT PERFECT BECAUSE THE TOOLTIP COULD THEN PERHAPS GO PARTIALLY THROUGH THE CUSTOM BTN.. THEN GOTTA MESS WITH WinSetTransColor/WinSetRegion, IT'S JUST A BIG MESS.. AND NEEDS BINARY SEARCH
  167. ;TO DO AT MOST 9 PixelGetColor CALLS FOR FULL WIDTH OF AD BTN OVERLAY (TAKES ABOUT 140 MSEC), INSTEAD OF 354 CALLS (TAKES ABOUT 5891 MSEC!!)]
  168. ;[I GUESS I'LL HAVE TO DO THIS INSTEAD: FIRST HORIZONTAL ROW OF BLACK PIXELS, THEN AT THE END OF THE ROW OF BLACK PIXELS, TEMPORARILY TURNING THE AD BTN OVERLAYS OFF SO IT CAN CHECK <-\
  169. ;VERTICALLY AS WELL, TO SEE WHERE THE BLACK PIXELS STOP GOING DOWNWARDS FROM THE RIGHT EDGE OF THE TOOLTIP.. THAT'S LIKE A SAFE SPOT WITH ONLY BLACK PIXELS TO EXPECT. THEN CHANGING THE \
  170. ;AD BTN OVERLAYS AND TURNING THEM BACK ON. AND WHEN THE PIXEL AT THE TOP ISN'T DETECT ANYMORE IN A NEW MOUSEMOVE EVENT, IT RESETS THE AD BTN OVERLAYS]                                    |
  171. ;[NO NEED TO LOOP OVER BOTTOM PIXELS OFC]                                                                                                                                                 |
  172. ;[REV0, SKIP]IF BOOL_1 = TRUE, THEN { LOOP OVER TOP PIXELS, USING RESULT FOR TOP-RIGHT GUI WIDTH AND IF BOOL_2 = TRUE THEN ALSO FOR BOTTOM-RIGHT GUI WIDTH }                              |
  173. ;IF BOOL_1 = TRUE, THEN { LOOP OVER HORIZONTAL TOP PIXELS, USING RESULT FOR TOP-RIGHT GUI WIDTH AND BOTTOM-RIGHT GUI WIDTH, [π—¨π—¦π—˜ 𝗫 𝗒π—₯ π—¦π—’π— π—˜π—§π—›π—œπ—‘π—š π—˜π—Ÿπ—¦π—˜ 𝗙𝗒π—₯ π—”π—Ÿπ—œπ—šπ—‘π— π—˜π—‘π—§?], LOOP OVER VERTICAL TOP  /
  174. ;PIXELS FROM TOP TO BOTTOM, USING RESULT FOR TOP-RIGHT GUI HEIGHT AND BOTTOM-RIGHT GUI HEIGHT, [π—¨π—¦π—˜ 𝗬 𝗒π—₯ π—¦π—’π— π—˜π—§π—›π—œπ—‘π—š π—˜π—Ÿπ—¦π—˜ 𝗙𝗒π—₯ π—”π—Ÿπ—œπ—šπ—‘π— π—˜π—‘π—§? IT'S PROBABLY F'D, SEE OTHER SUGGESTION ABOVE PSEUDOCODE]}
  175.     }
  176. else
  177. ToolTip("OFF TOP BTN BAR " eventInfo.Pt.Y)
  178. }
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198. #HotIf (MouseIsOver("ahk_group CustomOutlookNonClickableOverlays"))
  199. *LButton::WinActivate("E-mail ahk_class Olk Host")
  200.  
  201. ; Makes Outlook active when it needs to be while a click is happening on the custom refresh button
  202. #HotIf (MouseIsOverCustomOutlookRefreshButton())
  203. *LButton::
  204. {
  205.     WinActivate("E-mail ahk_class Olk Host")
  206.     Send("{LButton down}")
  207.     KeyWait("LButton")
  208.     Send("{LButton up}")
  209.     WinActivate("E-mail ahk_class Olk Host")
  210. }
  211.  
  212. ; CURRENTLY ONLY WORKS FOR OUTLOOK DARK MODE
  213. #HotIf (MouseIsOver("E-mail ahk_class Olk Host"))
  214. *LButton::
  215. {
  216.     WinGetClientPos(&outlookX, &outlookY,,, "E-mail ahk_class Olk Host")
  217.     MouseGetPos(&cursorX, &cursorY)
  218.  
  219.     ; I have retrieved screen pos of pixels while in maximized Outlook wnd. Then made pos relative by incrementing once, since Outlook's x,y client pos was -1,-1 and I've added that to it
  220.     switch (cursorX)
  221.     {
  222.         ; Skips clicks on left side of inbox that otherwise allows you to resize, which interferes with the Outlook overlays feature
  223.         case outlookX + 354, outlookX + 355, outlookX + 356, outlookX + 357:
  224.            resizeLinePixelRowStart := outlookX + 353
  225.  
  226.             if (cursorY >= outlookY + 136)
  227.                 for (iteratedPixel in [0x141414, 0x141414, 0x3D3D3D, 0x3D3D3D])
  228.                     if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  229.                         return
  230.         ; Skips clicks on right side of inbox that otherwise allows you to resize, which interferes with the Outlook overlays feature
  231.         case outlookX + 733, outlookX + 734, outlookX + 735, outlookX + 736:
  232.            resizeLinePixelRowStart := outlookX + 732
  233.  
  234.             switch (cursorY)
  235.             {
  236.                 case outlookY + 124:
  237.                    for (iteratedPixel in [0x0F0F0F, 0x0F0F0F, 0x0F0F0F, 0x0F0F0F])
  238.                         if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  239.                             return
  240.                 case outlookY + 125:
  241.                    for (iteratedPixel in [0x101010, 0x101010, 0x101010, 0x101010])
  242.                         if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  243.                             return
  244.                 case outlookY + 126:
  245.                    for (iteratedPixel in [0x121212, 0x121212, 0x121212, 0x121212])
  246.                         if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  247.                             return
  248.                 case outlookY + 127, outlookY + 128:
  249.                    for (iteratedPixel in [0x131313, 0x131313, 0x131313, 0x131313])
  250.                         if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  251.                             return
  252.                 case outlookY + 129, outlookY + 130, outlookY + 131, outlookY + 132:
  253.                    for (iteratedPixel in [0x141414, 0x141414, 0x141414, 0x141414])
  254.                         if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  255.                             return
  256.                 case outlookY + 133:
  257.                    for (iteratedPixel in [0x131313, 0x141414, 0x141414, 0x141414])
  258.                         if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  259.                             return
  260.                 case outlookY + 134:
  261.                    for (iteratedPixel in [0x121212, 0x141414, 0x141414, 0x141414])
  262.                         if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  263.                             return
  264.                 case outlookY + 135:
  265.                    for (iteratedPixel in [0x121212, 0x131313, 0x141414, 0x141414])
  266.                         if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  267.                             return
  268.                 default:
  269.                     if (cursorY >= outlookY + 136)
  270.                         for (iteratedPixel in [0x111111, 0x131313, 0x141414, 0x141414])
  271.                             if (PixelGetColor(resizeLinePixelRowStart + A_Index, cursorY) = iteratedPixel)
  272.                                 return
  273.             }
  274.     }
  275.  
  276.     Send("{LButton down}"), KeyWait("LButton"), Send("{LButton up}")
  277. }
  278.  
  279. class Point
  280. {
  281.     X: i32, Y: i32
  282. }
  283.  
  284. /*
  285. Example usage: (pointerDeviceEventHook := PointerDeviceHook("Move|LButton Down|LButton Up", HandlePointerDeviceEvent)).Start()
  286.  
  287. /** @param {PointerDeviceHook.EventInfo} eventInfo Pointer device event info */`
  288. HandlePointerDeviceEvent(eventInfo)
  289. {
  290.     ToolTip(Format("
  291.    (
  292.        x{1}, y{2}
  293.         EventAction : {3}
  294.         EventKey    : {4}
  295.         KeyUsageCount   : {5}
  296.         KeyUsageTime    : {6}
  297.         PressDuration   : {7}
  298.         IsPenAction : {8}
  299.    )", eventInfo.Pt.X, eventInfo.Pt.Y, eventInfo.Action, eventInfo.Key, eventInfo.KeyUsageCount, eventInfo.KeyUsageTime, eventInfo.KeyPressDuration, eventInfo.IsPenAction))
  300. }
  301. */
  302. class PointerDeviceHook
  303. {
  304.     class InternalEventInfo
  305.     {
  306.         Pt: Point
  307.         MouseData: i32 ; Necessary cast to `Int`
  308.         Flags: u32
  309.         Time: u32
  310.         ExtraInfo: uptr
  311.     }
  312.  
  313.     class EventInfo
  314.     {
  315.         Pt => this._IsPtAdaptive ? PointerDeviceHook.EventInfo.LatestPt : this._Pt
  316.  
  317.         /** @prop {string} Action The event action */
  318.         Action => this._IsActionAdaptive ? (PointerDeviceHook.EventInfo.LatestAction ?? this._Action) : this._Action
  319.  
  320.         /** @prop {string} Key The event key */
  321.         Key => PointerDeviceHook.EventInfo.IsKeyPressedDown ? PointerDeviceHook.EventInfo.RetainedKey : this._Key
  322.  
  323.         /** @prop {integer} KeyUsageCount Count how many times a key gets pressed in a short time (KeyUsageCountTimeThreshold) */
  324.         KeyUsageCount => PointerDeviceHook.EventInfo.IsKeyPressedDown ? PointerDeviceHook.EventInfo.RetainedKeyUsageCount : this._KeyUsageCount
  325.  
  326.         /** @prop {string} KeyUsageTime The time when the event key was pressed, scrolled, or used for a pen action */
  327.         KeyUsageTime => PointerDeviceHook.EventInfo.IsKeyPressedDown ? PointerDeviceHook.EventInfo.RetainedKeyUsageTime : this._KeyUsageTime
  328.  
  329.         /** @prop {integer} KeyPressDuration The time elapsed since this key was pressed */
  330.         KeyPressDuration => (this.KeyUsageTime ? A_TickCount - this.KeyUsageTime : 0)
  331.  
  332.         /** @prop {integer} IsPenAction Whether or not the event is caused by a pen pointer device (not detected when using drawing tablet) */
  333.         IsPenAction => PointerDeviceHook.EventInfo.IsKeyPressedDown ? PointerDeviceHook.EventInfo.RetainedIsPenAction : this._IsPenAction
  334.  
  335.         /** @prop {boolean} IsKeyPressedDown The hook does not repeatedly trigger the down event while a key is pressed down, so those `onEvent` callbacks use timer & keeps relevant info */
  336.         static IsKeyPressedDown := false
  337.  
  338.         static __New() => this.LatestPt := Point()
  339.         __New() => this._Pt := Point()
  340.     }
  341.  
  342.     /** @prop {Map} MsgList A list of message codes and actions (the commented wheel actions can also be used in the `PointerDeviceHook` constructor) */
  343.     MsgList := Map(
  344.         512, "Move",
  345.         513, "LButton Down",
  346.         514, "LButton Up",
  347.         516, "RButton Down",
  348.         517, "RButton Up",
  349.         519, "MButton Down",
  350.         520, "MButton Up",
  351.         523, "XButton{:d} Down",
  352.         524, "XButton{:d} Up")
  353.         ;β€”β€”, "WheelUp"
  354.         ;β€”β€”, "WheelDown"
  355.  
  356.     /** @prop {integer} ProcHandle SetWindowsHookEx */
  357.     ProcHandle := 0
  358.  
  359.     /** @prop {Map} PriorKeyObjects The map logs the time of when keys were previously pressed, as well as the count (both saved inside an object which is associated with a key) */
  360.     PriorKeyObjects := Map()
  361.  
  362.     /** @prop {integer} KeyUsageCountTimeThreshold The time in which the usage of the event key gets counted, or reset when the time threshold is reached (milliseconds) */
  363.     KeyUsageCountTimeThreshold := 500
  364.  
  365.     /**
  366.      * @param {string} [action="All"] Move, LButton Down, MButton Up, etc (the `MsgList` property shows all of them)
  367.      * @param {(hookObj) => Integer} onEvent This callback gets called on the event (to block mouse actions the callback must return true w/ default value `shouldMaintainResponsiveness`)
  368.      * @param {integer} [shouldMaintainResponsiveness=false] Default is False, causing it to call `onEvent` in this thread in favor of mouse-action-blocking capability (consider using timer
  369.      * in `onEvent`). Specify True to call it in a different thread if the `onEvent` code causes considerable mouse lag, as a result the Proc becomes incapable of blocking mouse actions
  370.      * @param {integer} [criticalMode=0] Default is Disabled Mode. A (positive) Enabled Mode value is the message check interval. Specifying -1 turns on Critical but disables message checks
  371.      */
  372.     __New(action := "All", onEvent := (*) => 0, shouldMaintainResponsiveness := false, criticalMode := 0)
  373.     {
  374.         static WM_LBUTTONDOWN := 0x0201, WM_LBUTTONUP := 0x0202, WM_RBUTTONDOWN := 0x0204, WM_RBUTTONUP := 0x0205, WM_MBUTTONDOWN := 0x0207, WM_MBUTTONUP := 0x0208, WM_MOUSEWHEEL := 0x020A
  375.             , WM_XBUTTONDOWN := 0x020B, WM_XBUTTONUP := 0x020C, LLMHF_INJECTED := 0x00000001, MI_WP_SIGNATURE := 0xFF515700, SIGNATURE_MASK := 0xFFFFFF00
  376.  
  377.         ; This callback gets executed when a pointer-device hook event occurs. The fast mode should be used only when it is known exactly which thread(s) this callback will be called from
  378.         this.InternalCallback := CallbackCreate(PointerDeviceProc, (criticalMode && criticalMode != "Off") ? "F" : unset, 3)
  379.  
  380.         PointerDeviceProc(nCode, wParam, lParam)
  381.         {
  382.             if (criticalMode = -1 || criticalMode)
  383.                 Critical(criticalMode)
  384.  
  385.             internalEventInfo := StructFromPtr(PointerDeviceHook.InternalEventInfo, lParam)
  386.             eventInfo := PointerDeviceHook.EventInfo()
  387.  
  388.             ; `internalEventInfo.MouseData` contains a reserved low-order word, which we don't need, and the high-order word is the leftmost 16 bits (bitshift removes the rest).
  389.             ; `PointerDeviceHook.EventInfo.IsKeyPressedDown` is mainly set at this point so that the up event will also stop the repeated down event timer when the up action isn't hooked
  390.             switch (wParam)
  391.             {
  392.                 case WM_MOUSEWHEEL: eventInfo._Action := (internalEventInfo.MouseData >> 16) > 0 ? "WheelUp" : "WheelDown", PointerDeviceHook.EventInfo.IsKeyPressedDown := false
  393.                 case WM_XBUTTONDOWN: eventInfo._Action := Format(this.MsgList[wParam], internalEventInfo.MouseData >> 16), PointerDeviceHook.EventInfo.IsKeyPressedDown := true
  394.                 case WM_XBUTTONUP: eventInfo._Action := Format(this.MsgList[wParam], internalEventInfo.MouseData >> 16), PointerDeviceHook.EventInfo.IsKeyPressedDown := false
  395.                 case WM_LBUTTONDOWN, WM_RBUTTONDOWN, WM_MBUTTONDOWN: eventInfo._Action := this.MsgList[wParam], PointerDeviceHook.EventInfo.IsKeyPressedDown := true
  396.                 case WM_LBUTTONUP, WM_RBUTTONUP, WM_MBUTTONUP: eventInfo._Action := this.MsgList[wParam], PointerDeviceHook.EventInfo.IsKeyPressedDown := false
  397.                 default: eventInfo._Action := this.MsgList.Has(wParam) ? this.MsgList[wParam] : 0
  398.             }
  399.  
  400.             if (nCode < 0 || (action != "All" && !InStr(action, eventInfo._Action)))
  401.                 return CallNextHookEx(nCode, wParam, lParam)
  402.  
  403.             eventInfo._IsPtAdaptive := eventInfo._IsActionAdaptive := false
  404.             eventInfo._KeyUsageTime := eventInfo._KeyUsageCount := eventInfo._Key := 0
  405.             eventInfo._Pt.X := internalEventInfo.Pt.X
  406.             eventInfo._Pt.Y := internalEventInfo.Pt.Y
  407.  
  408.             if (eventInfo._Action && eventInfo._Action != "Move")
  409.             {
  410.                 if (!this.PriorKeyObjects.Has(eventInfo._Action))
  411.                     this.PriorKeyObjects[eventInfo._Action] := {Time: internalEventInfo.Time, Count: 0}
  412.  
  413.                 priorKey := this.PriorKeyObjects[eventInfo._Action]
  414.                 eventInfo._Key := eventInfo._Action
  415.                 eventInfo._KeyUsageCount := priorKey.Count += internalEventInfo.Time - priorKey.Time < this.KeyUsageCountTimeThreshold ? 1 : -priorKey.Count + 1 ; Resets to 1 if false
  416.                 eventInfo._KeyUsageTime := priorKey.Time := internalEventInfo.Time
  417.                 eventInfo._IsPenAction := DetermineIsPenAction(internalEventInfo.ExtraInfo)
  418.                
  419.                 if (PointerDeviceHook.EventInfo.IsKeyPressedDown)
  420.                 {
  421.                     keyDownEventInfo := eventInfo.Clone()
  422.                     keyDownEventInfo._IsPtAdaptive := keyDownEventInfo._IsActionAdaptive := true
  423.                     PointerDeviceHook.EventInfo.LatestPt.X := eventInfo._Pt.X
  424.                     PointerDeviceHook.EventInfo.LatestPt.Y := eventInfo._Pt.Y
  425.                     PointerDeviceHook.EventInfo.LatestAction := unset
  426.                     PointerDeviceHook.EventInfo.RetainedKey := eventInfo._Key
  427.                     PointerDeviceHook.EventInfo.RetainedKeyUsageCount := eventInfo._KeyUsageCount
  428.                     PointerDeviceHook.EventInfo.RetainedKeyUsageTime := internalEventInfo.Time
  429.                     PointerDeviceHook.EventInfo.RetainedIsPenAction := eventInfo._IsPenAction
  430.                     SetTimer(() => (this.ProcHandle && PointerDeviceHook.EventInfo.IsKeyPressedDown ? onEvent(keyDownEventInfo) : SetTimer(, 0)), 50)
  431.                 }
  432.             }
  433.             else if (PointerDeviceHook.EventInfo.IsKeyPressedDown)
  434.             {
  435.                 PointerDeviceHook.EventInfo.LatestPt.X := eventInfo._Pt.X
  436.                 PointerDeviceHook.EventInfo.LatestPt.Y := eventInfo._Pt.Y
  437.                 PointerDeviceHook.EventInfo.LatestAction := eventInfo._Action
  438.             }
  439.             else
  440.                 eventInfo._IsPenAction := DetermineIsPenAction(internalEventInfo.ExtraInfo)
  441.  
  442.             if (shouldMaintainResponsiveness)
  443.             {
  444.                 SetTimer(() => onEvent(eventInfo), -1)
  445.  
  446.                 return CallNextHookEx(nCode, wParam, lParam)
  447.             }
  448.             else
  449.                 return onEvent(eventInfo) && !(internalEventInfo.Flags & LLMHF_INJECTED) ? true : CallNextHookEx(nCode, wParam, lParam)
  450.         }
  451.  
  452.         DetermineIsPenAction(extraInfo) => ((extraInfo & SIGNATURE_MASK) = MI_WP_SIGNATURE)
  453.         CallNextHookEx(nCode, wParam, lParam) => DllCall("CallNextHookEx", "Ptr", 0, "Int", nCode, "UPtr", wParam, "Ptr", lParam)
  454.     }
  455.  
  456.     /** Warning: Take caution when blocking mouse actions, you should not call this inside a mouse hotkey prefixed w/ the (~) tilde symbol (to make `Stop` unblock mouse actions properly) */
  457.     Start()
  458.     {
  459.         if (!this.ProcHandle)
  460.             this.ProcHandle := DllCall("SetWindowsHookEx", "Int", WH_MOUSE_LL := 14, "Ptr", this.InternalCallback, "Ptr", GetModuleHandle(), "UInt", 0)
  461.  
  462.         GetModuleHandle() => DllCall("GetModuleHandle", "UInt", 0, "Ptr")
  463.     }
  464.    
  465.     Stop()
  466.     {
  467.         if (this.ProcHandle && DllCall("UnhookWindowsHookEx", "Ptr", this.ProcHandle))
  468.             this.ProcHandle := 0
  469.     }
  470.  
  471.     __Delete() => (this.InternalCallback && (this.Stop(), CallbackFree(this.InternalCallback), this.InternalCallback := 0))
  472. }
  473.  
  474. MouseIsOver(winTitle, winText?, excludeTitle?, excludeText?) => (MouseGetPos(,, &winId), WinExist(winTitle " ahk_id " winId, winText?, excludeTitle?, excludeText?))
  475.  
  476. MouseIsOverCustomOutlookRefreshButton()
  477. {
  478.     try return (MouseGetPos(,, &winId, &control), WinExist(A_ScriptName " ahk_class AutoHotkeyGUI ahk_id " winId) && control = "Button1")
  479.     return false
  480. }
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513. ; ------------------------------------------------------------------------ BELOW ARE SOME OTHER FILES I HAD ------------------------------------------------------------------------
  514.  
  515. /*
  516. WS_EX_NOACTIVATE is useless? maybe not, the click skip didn't work so that seemed useless but it's also supposed to skip activation through other means
  517. */
  518.  
  519. /*
  520. [When it's done, reply / edit reply with Lorenzo501 in issue of the two github repos that tried to fix it but failed, one I have starred with Lorenzo501, and one with Infinity-Surfer that
  521. needs to unstar, also edit the msg in the ExplorerPatcher's newoutlookpatcher channel, and maybe test Tgames' Outlook trick on laptop, could mention it on the issue discussions too]
  522. [When it's done, should probably make the stuff in the WinEvent handler use "try" in case Outlook crashes.. go kill the process and see if there's an error]
  523. [On Outlook foreground event, resize and move event, but these events should get hooked in HandleCreatedOutlookEvent when it ends because Outlook is temporarily transparent and active]
  524. [Make sure the other Outlook features still work, because they probably relied on Outlook being active but especially if the new Refresh btn gets clicked, Outlook might be seen as inactive
  525. but maybe I can just make the LButton hotkey use MouseIsOver instead of WinActive.. I doubt there's a better solution]
  526. [make it search for the white pixels in case the layout has been stretched, because then [Adv] moves with it]
  527. These are always there when you check for the position within the wnd instead of the screen (resizing/moving the wnd doesn't matter then apart from keeping it in the top-left corner).
  528. I can check on several points in the wnd ad section to detect if there are white pixels of the [Adv] symbol, and only then mask the ad section.
  529.  
  530. [I have already removed the Sync button that you have by default in the View tab]
  531. [Mention in Time Saver to multi-line automation comment that the Sync button in the View tab of New Outlook is replaced by a "Refresh e-mails" button that overlays the ad section
  532. and that it's recommended to do the following: Go to the View tab > More options > Customize > Uncheck Synchronize > Save]
  533. To put something actually useful in the empty ad section, just add a button that says "Refresh e-mails" and when clicked, sends F9
  534. Verzonden en ontvangen e-mail synchroniseren: F9
  535.  
  536. [Make sure to only use dark colors for the GUI when dark mode is used, otherwise light colors. and only need to check for it in the Outlook foreground event, not the resize and move event]
  537. FFFFFF on [Adv] and 292929 around/inside [Adv] << ON DARK MODE
  538. 000000 on [Adv] and FFFFFF around/inside [Adv] << ON LIGHT MODE
  539.  
  540. --------[x]--[y]
  541.  
  542. top-left corner of ad
  543. Screen: 356, 131
  544. Window: 364, 139
  545. Client: 357, 132
  546.  
  547. bottom-left corner of ad
  548. Screen: 356, 210
  549. Window: 364, 218
  550. Client: 357, 211
  551.  
  552. top-right corner of ad
  553. Screen: 732, 131
  554. Window: 740, 139
  555. Client: 733, 132
  556.  
  557. bottom-right corner of ad
  558. Screen: 732, 210
  559. Window: 740, 218
  560. Client: 733, 211
  561. */
  562.  
  563. /*
  564. #Requires AutoHotkey 2.0
  565. A_CoordModePixel := "Screen"
  566.  
  567. loop
  568. {
  569. a := PixelGetColor(615, 145)
  570. b := PixelGetColor(616, 145)
  571. c := PixelGetColor(617, 145)
  572. d := PixelGetColor(618, 145)
  573. e := PixelGetColor(619, 145)
  574. f := PixelGetColor(620, 145)
  575. g := PixelGetColor(621, 145)
  576. h := PixelGetColor(622, 145)
  577. i := PixelGetColor(623, 145)
  578. j := PixelGetColor(624, 145)
  579. k := PixelGetColor(625, 145)
  580. tooltip("615 = " a "`n616 = " b "`n617 = " c "`n618 = " d "`n619 = " e "`n620 = " f "`n621 = " g "`n622 = " h "`n623 = " i "`n624 = " j "`n625 = " k)
  581. }
  582. */
  583.  
  584. /*
  585. #Requires AutoHotkey 2.0
  586. A_CoordModePixel := "Screen"
  587.  
  588. ; 732, 123
  589. ; to
  590. ; 735, 260
  591.  
  592. F8::
  593. {
  594. currentX := 732
  595. currentY := 123
  596. A_Clipboard := ""
  597.  
  598. loop ; TO FIND OUT ALL COLORS OF THE RESIZE LINE ON THE RIGHT
  599. {
  600.     loop
  601.     {
  602.         if (currentX = 732)
  603.             A_Clipboard .= "732-735," currentY " = "
  604.  
  605.         A_Clipboard .= PixelGetColor(currentX, currentY) ", "
  606.  
  607.         if (currentX = 735)
  608.         {
  609.             currentX := 732
  610.             A_Clipboard .= "`n"
  611.  
  612.             break
  613.         }
  614.         else
  615.             ++currentX
  616.     }
  617.  
  618.     if (currentY = 260)
  619.         break
  620.     else
  621.         ++currentY
  622. }
  623. ToolTip("Done")
  624. }
  625.  
  626. these need to skip clicks when the color ΜΆuΜΆnΜΆdΜΆeΜΆr near the cursor is found but also the pixel next to it (the other pixel), to make sure that the resize element is being hovered and not
  627. something with the same color
  628.  
  629. Screen X and color [RESIZE LINE ON THE LEFT]:
  630. 353, 141414
  631. 354, 141414
  632. 355, 3D3D3D
  633. 356, 3D3D3D
  634.  
  635. Screen X, Y and color [RESIZE LINE ON THE RIGHT, MORE COMPLICATED COLORS AT THE TOP]:
  636. 732, 123
  637. to
  638. 735, 260
  639. RESULTS:    check these two pixels when on any of these four pixels (X axes from top to bottom)
  640.    X     Y  __||__    __||__             __1
  641.  732-735,123 = 0x0F0F0F, 0x0F0F0F, 0x0F0F0F, 0x0F0F0F,_1
  642.  732-735,124 = 0x101010, 0x101010, 0x101010, 0x101010,_1
  643.  732-735,125 = 0x121212, 0x121212, 0x121212, 0x121212,__2!
  644. 732-735,126 = 0x131313, 0x131313, 0x131313, 0x131313,
  645. 732-735,127~= 0x131313, 0x131313, 0x131313, 0x131313,__4!
  646. /732-735,128 = 0x141414, 0x141414, 0x141414, 0x141414,
  647. 732-735,129 = 0x141414, 0x141414, 0x141414, 0x141414,
  648. 732-735,130 = 0x141414, 0x141414, 0x141414, 0x141414,
  649. 732-735,131 = 0x141414, 0x141414, 0x141414, 0x141414,_1!
  650. /732-735,132~= 0x131313, 0x141414, 0x141414, 0x141414, ..__1!
  651.  732-735,133 = 0x121212, 0x141414, 0x141414, 0x141414,   ___1!
  652.  732-735,134/=_0x121212,/0x131313,/0x141414,_0x141414,   ____126!..
  653. /732-735,135 = 0x111111, 0x131313, 0x141414, 0x141414,
  654. 732-735,136 = 0x111111, 0x131313, 0x141414, 0x141414,
  655. 732-735,137 = 0x111111, 0x131313, 0x141414, 0x141414,
  656. 732-735,138 = 0x111111, 0x131313, 0x141414, 0x141414,
  657. 732-735,139 = 0x111111, 0x131313, 0x141414, 0x141414,
  658. 732-735,140 = 0x111111, 0x131313, 0x141414, 0x141414,
  659. 732-735,141 = 0x111111, 0x131313, 0x141414, 0x141414,
  660. 732-735,142 = 0x111111, 0x131313, 0x141414, 0x141414,
  661. 732-735,143 = 0x111111, 0x131313, 0x141414, 0x141414,
  662. 732-735,144 = 0x111111, 0x131313, 0x141414, 0x141414,
  663. 732-735,145 = 0x111111, 0x131313, 0x141414, 0x141414,
  664. 732-735,146 = 0x111111, 0x131313, 0x141414, 0x141414,
  665. 732-735,147 = 0x111111, 0x131313, 0x141414, 0x141414,
  666. 732-735,148 = 0x111111, 0x131313, 0x141414, 0x141414,
  667. 732-735,149 = 0x111111, 0x131313, 0x141414, 0x141414,
  668. 732-735,150 = 0x111111, 0x131313, 0x141414, 0x141414,
  669. 732-735,151 = 0x111111, 0x131313, 0x141414, 0x141414,
  670. 732-735,152 = 0x111111, 0x131313, 0x141414, 0x141414,
  671. 732-735,153 = 0x111111, 0x131313, 0x141414, 0x141414,
  672. 732-735,154 = 0x111111, 0x131313, 0x141414, 0x141414,
  673. 732-735,155 = 0x111111, 0x131313, 0x141414, 0x141414,
  674. 732-735,156 = 0x111111, 0x131313, 0x141414, 0x141414,
  675. 732-735,157 = 0x111111, 0x131313, 0x141414, 0x141414,
  676. 732-735,158 = 0x111111, 0x131313, 0x141414, 0x141414,
  677. 732-735,159 = 0x111111, 0x131313, 0x141414, 0x141414,
  678. 732-735,160 = 0x111111, 0x131313, 0x141414, 0x141414,
  679. 732-735,161 = 0x111111, 0x131313, 0x141414, 0x141414,
  680. 732-735,162 = 0x111111, 0x131313, 0x141414, 0x141414,
  681. 732-735,163 = 0x111111, 0x131313, 0x141414, 0x141414,
  682. 732-735,164 = 0x111111, 0x131313, 0x141414, 0x141414,
  683. 732-735,165 = 0x111111, 0x131313, 0x141414, 0x141414,
  684. 732-735,166 = 0x111111, 0x131313, 0x141414, 0x141414,
  685. 732-735,167 = 0x111111, 0x131313, 0x141414, 0x141414,
  686. 732-735,168 = 0x111111, 0x131313, 0x141414, 0x141414,
  687. 732-735,169 = 0x111111, 0x131313, 0x141414, 0x141414,
  688. 732-735,170 = 0x111111, 0x131313, 0x141414, 0x141414,
  689. 732-735,171 = 0x111111, 0x131313, 0x141414, 0x141414,
  690. 732-735,172 = 0x111111, 0x131313, 0x141414, 0x141414,
  691. 732-735,173 = 0x111111, 0x131313, 0x141414, 0x141414,
  692. 732-735,174 = 0x111111, 0x131313, 0x141414, 0x141414,
  693. 732-735,175 = 0x111111, 0x131313, 0x141414, 0x141414,
  694. 732-735,176 = 0x111111, 0x131313, 0x141414, 0x141414,
  695. 732-735,177 = 0x111111, 0x131313, 0x141414, 0x141414,
  696. 732-735,178 = 0x111111, 0x131313, 0x141414, 0x141414,
  697. 732-735,179 = 0x111111, 0x131313, 0x141414, 0x141414,
  698. 732-735,180 = 0x111111, 0x131313, 0x141414, 0x141414,
  699. 732-735,181 = 0x111111, 0x131313, 0x141414, 0x141414,
  700. 732-735,182 = 0x111111, 0x131313, 0x141414, 0x141414,
  701. 732-735,183 = 0x111111, 0x131313, 0x141414, 0x141414,
  702. 732-735,184 = 0x111111, 0x131313, 0x141414, 0x141414,
  703. 732-735,185 = 0x111111, 0x131313, 0x141414, 0x141414,
  704. 732-735,186 = 0x111111, 0x131313, 0x141414, 0x141414,
  705. 732-735,187 = 0x111111, 0x131313, 0x141414, 0x141414,
  706. 732-735,188 = 0x111111, 0x131313, 0x141414, 0x141414,
  707. 732-735,189 = 0x111111, 0x131313, 0x141414, 0x141414,
  708. 732-735,190 = 0x111111, 0x131313, 0x141414, 0x141414,
  709. 732-735,191 = 0x111111, 0x131313, 0x141414, 0x141414,
  710. 732-735,192 = 0x111111, 0x131313, 0x141414, 0x141414,
  711. 732-735,193 = 0x111111, 0x131313, 0x141414, 0x141414,
  712. 732-735,194 = 0x111111, 0x131313, 0x141414, 0x141414,
  713. 732-735,195 = 0x111111, 0x131313, 0x141414, 0x141414,
  714. 732-735,196 = 0x111111, 0x131313, 0x141414, 0x141414,
  715. 732-735,197 = 0x111111, 0x131313, 0x141414, 0x141414,
  716. 732-735,198 = 0x111111, 0x131313, 0x141414, 0x141414,
  717. 732-735,199 = 0x111111, 0x131313, 0x141414, 0x141414,
  718. 732-735,200 = 0x111111, 0x131313, 0x141414, 0x141414,
  719. 732-735,201 = 0x111111, 0x131313, 0x141414, 0x141414,
  720. 732-735,202 = 0x111111, 0x131313, 0x141414, 0x141414,
  721. 732-735,203 = 0x111111, 0x131313, 0x141414, 0x141414,
  722. 732-735,204 = 0x111111, 0x131313, 0x141414, 0x141414,
  723. 732-735,205 = 0x111111, 0x131313, 0x141414, 0x141414,
  724. 732-735,206 = 0x111111, 0x131313, 0x141414, 0x141414,
  725. 732-735,207 = 0x111111, 0x131313, 0x141414, 0x141414,
  726. 732-735,208 = 0x111111, 0x131313, 0x141414, 0x141414,
  727. 732-735,209 = 0x111111, 0x131313, 0x141414, 0x141414,
  728. 732-735,210 = 0x111111, 0x131313, 0x141414, 0x141414,
  729. 732-735,211 = 0x111111, 0x131313, 0x141414, 0x141414,
  730. 732-735,212 = 0x111111, 0x131313, 0x141414, 0x141414,
  731. 732-735,213 = 0x111111, 0x131313, 0x141414, 0x141414,
  732. 732-735,214 = 0x111111, 0x131313, 0x141414, 0x141414,
  733. 732-735,215 = 0x111111, 0x131313, 0x141414, 0x141414,
  734. 732-735,216 = 0x111111, 0x131313, 0x141414, 0x141414,
  735. 732-735,217 = 0x111111, 0x131313, 0x141414, 0x141414,
  736. 732-735,218 = 0x111111, 0x131313, 0x141414, 0x141414,
  737. 732-735,219 = 0x111111, 0x131313, 0x141414, 0x141414,
  738. 732-735,220 = 0x111111, 0x131313, 0x141414, 0x141414,
  739. 732-735,221 = 0x111111, 0x131313, 0x141414, 0x141414,
  740. 732-735,222 = 0x111111, 0x131313, 0x141414, 0x141414,
  741. 732-735,223 = 0x111111, 0x131313, 0x141414, 0x141414,
  742. 732-735,224 = 0x111111, 0x131313, 0x141414, 0x141414,
  743. 732-735,225 = 0x111111, 0x131313, 0x141414, 0x141414,
  744. 732-735,226 = 0x111111, 0x131313, 0x141414, 0x141414,
  745. 732-735,227 = 0x111111, 0x131313, 0x141414, 0x141414,
  746. 732-735,228 = 0x111111, 0x131313, 0x141414, 0x141414,
  747. 732-735,229 = 0x111111, 0x131313, 0x141414, 0x141414,
  748. 732-735,230 = 0x111111, 0x131313, 0x141414, 0x141414,
  749. 732-735,231 = 0x111111, 0x131313, 0x141414, 0x141414,
  750. 732-735,232 = 0x111111, 0x131313, 0x141414, 0x141414,
  751. 732-735,233 = 0x111111, 0x131313, 0x141414, 0x141414,
  752. 732-735,234 = 0x111111, 0x131313, 0x141414, 0x141414,
  753. 732-735,235 = 0x111111, 0x131313, 0x141414, 0x141414,
  754. 732-735,236 = 0x111111, 0x131313, 0x141414, 0x141414,
  755. 732-735,237 = 0x111111, 0x131313, 0x141414, 0x141414,
  756. 732-735,238 = 0x111111, 0x131313, 0x141414, 0x141414,
  757. 732-735,239 = 0x111111, 0x131313, 0x141414, 0x141414,
  758. 732-735,240 = 0x111111, 0x131313, 0x141414, 0x141414,
  759. 732-735,241 = 0x111111, 0x131313, 0x141414, 0x141414,
  760. 732-735,242 = 0x111111, 0x131313, 0x141414, 0x141414,
  761. 732-735,243 = 0x111111, 0x131313, 0x141414, 0x141414,
  762. 732-735,244 = 0x111111, 0x131313, 0x141414, 0x141414,
  763. 732-735,245 = 0x111111, 0x131313, 0x141414, 0x141414,
  764. 732-735,246 = 0x111111, 0x131313, 0x141414, 0x141414,
  765. 732-735,247 = 0x111111, 0x131313, 0x141414, 0x141414,
  766. 732-735,248 = 0x111111, 0x131313, 0x141414, 0x141414,
  767. 732-735,249 = 0x111111, 0x131313, 0x141414, 0x141414,
  768. 732-735,250 = 0x111111, 0x131313, 0x141414, 0x141414,
  769. 732-735,251 = 0x111111, 0x131313, 0x141414, 0x141414,
  770. 732-735,252 = 0x111111, 0x131313, 0x141414, 0x141414,
  771. 732-735,253 = 0x111111, 0x131313, 0x141414, 0x141414,
  772. 732-735,254 = 0x111111, 0x131313, 0x141414, 0x141414,
  773. 732-735,255 = 0x111111, 0x131313, 0x141414, 0x141414,
  774. 732-735,256 = 0x111111, 0x131313, 0x141414, 0x141414,
  775. 732-735,257 = 0x111111, 0x131313, 0x141414, 0x141414,
  776. 732-735,258 = 0x111111, 0x131313, 0x141414, 0x141414,
  777. 732-735,259 = 0x111111, 0x131313, 0x141414, 0x141414,
  778. 732-735,260 = 0x111111, 0x131313, 0x141414, 0x141414,
  779. */
Advertisement
Comments
  • Lorenzo501
    3 hours
    1. ;WinSetTransColor is better but here's some WinSetRegion test code:
    2.  
    3. #Requires AutoHotkey 2.0
    4. #SingleInstance Force
    5.  
    6. ; --- PART 1: Example Setup (You will replace this with your actual GUI/Window setup) ---
    7. ; Assume these are your main GUI's (the one that will get the hole) details
    8. ; These are the screen coordinates and dimensions you used to SHOW your main GUI.
    9. mainX := 100
    10. mainY := 100
    11. mainWidth := 600
    12. mainHeight := 400
    13.  
    14. mainGui := Gui("-Caption")
    15. mainGui.Title := "Main GUI (Always On Top)"
    16. mainGui.BackColor := "Gray" ; To clearly see the hole
    17. mainGui.Opt("+AlwaysOnTop") ; Make it always on top
    18. mainGui.AddButton("x220 y350 w300", "Refresh e-mails")
    19. mainGui.Show("x" mainX " y" mainY " w" mainWidth " h" mainHeight)
    20.  
    21. ; Assume these are your child window's (the one being covered) details
    22. ; These are the screen coordinates and dimensions of the window that will define the hole.
    23. childX := 450
    24. childY := 400
    25. childWidth := 300
    26. childHeight := 150
    27.  
    28. childGui := Gui("-Caption")
    29. childGui.Title := "Child Window (Visible Through Hole)"
    30. childGui.BackColor := "Navy"
    31. childGui.Add("Text", "cWhite", "I am the child window!")
    32. childGui.Show("x" childX " y" childY " w" childWidth " h" childHeight)
    33.  
    34. ; Give windows a moment to appear
    35. Sleep 100
    36.  
    37. ; --- PART 2: Core Logic to Create the Hole in mainGui ---
    38.  
    39. ; IMPORTANT: Get the *current actual screen position* of the main GUI.
    40. ; This is important in case it was moved after being shown.
    41. WinGetPos(&CurrentMainScreenX, &CurrentMainScreenY, &CurrentMainWidth, &CurrentMainHeight, "ahk_id " mainGui.Hwnd)
    42.  
    43.  
    44. ; 1. Calculate the hole's coordinates *relative to the main GUI's top-left corner (0,0)*
    45. ; The WinSetRegion command expects relative coordinates for both the outer and inner polygons.
    46. HoleLeftRelative := childX - CurrentMainScreenX
    47. HoleTopRelative := childY - CurrentMainScreenY
    48. HoleRightRelative := HoleLeftRelative + childWidth
    49. HoleBottomRelative := HoleTopRelative + childHeight
    50.  
    51. ; 2. Construct the outer polygon string (representing the entire main GUI)
    52. ; Coordinates are 0-0 up to its current actual width and height.
    53. OuterPolygonString := "0-0 " CurrentMainWidth "-0 " CurrentMainWidth "-" CurrentMainHeight " 0-" CurrentMainHeight " 0-0"
    54.  
    55. ; 3. Construct the inner polygon string (representing the hole)
    56. InnerPolygonString := ""
    57. InnerPolygonString .= HoleLeftRelative "-" HoleTopRelative " "
    58. InnerPolygonString .= HoleRightRelative "-" HoleTopRelative " "
    59. InnerPolygonString .= HoleRightRelative "-" HoleBottomRelative " "
    60. InnerPolygonString .= HoleLeftRelative "-" HoleBottomRelative " "
    61. InnerPolygonString .= HoleLeftRelative "-" HoleTopRelative ; Close the polygon
    62.  
    63. ; 4. Combine the outer and inner polygons into the final region string
    64. RegionStringForWinSetRegion := OuterPolygonString "   " InnerPolygonString
    65.  
    66. ; 5. Apply the region to your main GUI
    67. WinSetRegion(RegionStringForWinSetRegion, "ahk_id " mainGui.Hwnd)
    68.  
    69. ; --- PART 3: Event Handlers (for clean exit) ---
    70. mainGui_OnClose() {
    71.     ExitApp
    72. }
    73.  
    74. childGui_OnClose() {
    75.     ExitApp
    76. }
Add Comment
Please, Sign In to add comment
Advertisement