1 (изменено: serzh82saratov, 2015-01-16 05:08:42)

Тема: AHK: Позиционирование окна, в зависимости от позиции мыши

Собственно цель, создание "самопального" ToolTip-а, который не будет скрыватся за краями экрана. Для основного монитора это сделать удалось:



Loop    {
    CoordMode, Mouse, Screen
    DllCall("DestroyWindow", "Ptr", hStatic)
    Gui, +AlwaysOnTop +ToolWindow -0x400000 -DPIScale
    Gui, Color, 95746A
    Gui, Font, Italic s18 cWhite, Times New Roman
    Gui Add, Text, hwndhStatic x10 y10 Center
    , Многострочный`nтекст`n`nHello,World!`nAHK forever!
    
    GuiControlGet, Pos, Pos, %hStatic%    
    h := PosY*2+PosH
    w := PosX*2+PosW
    
    MouseGetPos, mX, mY
    x := mX+15
    y := mY+15
    
    SysGet, Mon, Monitor 
    x := MonRight < x+w ? MonRight-w : x
    y := MonBottom < y+h ? MonBottom-h : y 
    
    Gui, Show, NA x%x% y%y% w%w% h%h%
    Sleep 50
}

Esc::
    ExitApp

но вот как это попроще сделать для двух мониторов (если они есть, и при любом их расположении друг к другу):
http://savepic.org/3355972.jpg
то есть скопировать поведение ToolTip-а при помещении курсора мыши к краям экрана.

Решено.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

2

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Может как-то можно создавать скрытый ToolTip с заданными размерами, и извлекать его позицию...

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

3

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Увидел функцию CalculatePopupWindowPosition function, но нигде не нашёл ни одного примера её использования. Кто нибудь знает как её "завести"?


x := A_ScreenWidth
y := A_ScreenHeight  
w := 222
h := 222

POINT := x & 0xFFFF | (y & 0xFFFF) << 16
SIZE := w & 0xFFFF | (h & 0xFFFF) << 16

DllCall("CalculatePopupWindowPosition"
    , "int64", POINT
    , "int64", SIZE
    , "UINT", 0x10000  ; TPM_WORKAREA
    , "int64", 0
    , "int64*", Res)
MsgBox, % "LOWORD = " Res & 0xFFFF
        . "`nHIWORD = " Res >> 16
Return
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

4

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Кроме 3-го, все параметры — указатели. Это ведь обозначено в объявлении функции звёздочками.

5

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Не наводит на мысли, я в этом ровным счётом ничего не понимаю.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

6

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Не знаете, что такое указатель? Однако в 5-м параметре вы его используете. Или это не вы код писали?

7

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Писал я. Везде добавил звёздочки, ничего. Делал по аналогии с другими функциями, "int64" - входящий параметр в виде структуры, "int64*" - исходящий параметр в виде структуры.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

8 (изменено: YMP, 2015-01-12 13:04:15)

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Нет, там указатели на структуры.

+ Вот их определения

typedef struct tagPOINT
{
    LONG  x;
    LONG  y;
} POINT

typedef struct tagSIZE
{
    LONG        cx;
    LONG        cy;
} SIZE

typedef struct tagRECT
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT

Т.е. вот так можно, например.


x := A_ScreenWidth
y := A_ScreenHeight  
w := 222
h := 222

VarSetCapacity( structs, 32, 0 )
NumPut( x, structs, 0, "int" ), NumPut( y, structs, 4, "int" )  ; POINT
NumPut( w, structs, 8, "int" ), NumPut( h, structs, 12, "int" ) ; SIZE

If !DllCall( "CalculatePopupWindowPosition"
    , "ptr", &structs
    , "ptr", &structs + 8
    , "uint", 0x10000        ; TPM_WORKAREA
    , "ptr", 0
    , "ptr", &structs + 16 )
{
    MsgBox, Ошибка.
    ExitApp
}
; Выходной RECT
left  := NumGet( structs, 16, "int" ), top    := NumGet( structs, 20, "int" )
right := NumGet( structs, 24, "int" ), bottom := NumGet( structs, 28, "int" )

MsgBox, %left% %top%`n%right% %bottom%

9

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

YMP
Большое спасибо за пример! Может не обращал нигде внимание до этого, но интересен также пример использования одной структуры под "всё".

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

10 (изменено: serzh82saratov, 2015-01-13 19:20:18)

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Сделал такой вариант:


Gui, Margin, 5, 5
Gui, Font, Italic s54 cWhite, Times New Roman
Gui, +AlwaysOnTop +ToolWindow -0x00400000 +E0x08000020 -DPIScale +Lastfound +HWNDhGui  +Owner
Gui, Color, 2F4F4F 
WinSet, TransParent, 200

1::   
    DllCall("DestroyWindow", "Ptr", hStatic)
    Gui Add, Text, hwndhStatic x5 y5, % "TickCount:`n" A_TickCount
    Gui, Show, % "NA AutoSize " (DllCall("IsWindowVisible", "uint", hGui) ? "" : "Hide") 
    If CalculatePopupWindowPosition(x, y, hGui, 15)
        Gui, Show, NA x%x% y%y%
    Return 
    
2:: Gui, Hide

CalculatePopupWindowPosition(byref left, byref top, hwnd, offset = 0, x = "", y = "")  { 
    VarSetCapacity(POINT, 8, 0), VarSetCapacity(structs, 24, 0)
    If (x = "" || y = "")
        DllCall("GetCursorPos", "ptr", &POINT)
    Else
        NumPut(x, POINT, 0, "int"), NumPut(y, POINT, 4, "int")  
    DHW := A_DetectHiddenWindows
    DetectHiddenWindows, On
    WinGetPos, , , w, h, ahk_id %hwnd% 
    DetectHiddenWindows, %DHW%
    NumPut(w + offset, structs, 0, "int"), NumPut(h + offset, structs, 4, "int") ; SIZE  
    If !DllCall("CalculatePopupWindowPosition"
        , "ptr", &POINT
        , "ptr", &structs
        , "int", 0x0040        ; TPM_VERTICAL
        , "ptr", 0
        , "ptr", &structs + 8)
        Return 0
    left  := NumGet(structs, 8, "int") + offset
    top := NumGet(structs, 12, "int") + offset 
    Return 1
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

11 (изменено: serzh82saratov, 2015-01-13 19:20:10)

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Или лучше так, чтобы мышь не наезжала на ToolTip.


Gui, Margin, 5, 5
Gui, Font, Italic s34 cWhite, Times New Roman
Gui, +AlwaysOnTop +ToolWindow -0x00400000 +E0x08000020 -DPIScale +Lastfound +HWNDhGui  +Owner
Gui, Color, 2F4F4F 
WinSet, TransParent, 200

1:: 
    DllCall("DestroyWindow", "Ptr", hStatic)
    Gui Add, Text, hwndhStatic x5 y5, % "TickCount:`n" A_TickCount
    Gui, Show, % "NA AutoSize " (DllCall("IsWindowVisible", "uint", hGui) ? "" : "Hide") 
    If CalculatePopupWindowPosition(x, y, hGui, 25)
        Gui, Show, NA x%x% y%y% 
    Return 
    
2:: Gui, Hide

CalculatePopupWindowPosition(byref left, byref top, hwnd, offset = 0, x = "", y = "")  { 
    VarSetCapacity(POINT, 8, 0), VarSetCapacity(structs, 24, 0)
    If (x = "" || y = "")
        DllCall("GetCursorPos", "ptr", &POINT)
    Else
        NumPut(x, POINT, 0, "int"), NumPut(y, POINT, 4, "int")  
    DHW := A_DetectHiddenWindows
    DetectHiddenWindows, On
    WinGetPos, , , w, h, ahk_id %hwnd% 
    DetectHiddenWindows, %DHW%
    NumPut(w + offset, structs, 0, "int"), NumPut(h + offset, structs, 4, "int") ; SIZE   
    Loop 2
    {
        If !DllCall("CalculatePopupWindowPosition"
            , "ptr", &POINT
            , "ptr", &structs
            , "int", [0, 0x0008][A_Index]
            , "ptr", 0
            , "ptr", &structs + 8)
            Return 0 
        _left := NumGet(structs, 8, "int"), _top := NumGet(structs, 12, "int") 
        If !(_left < NumGet(POINT, 0, "int") && _top < NumGet(POINT, 4, "int")  && (out := 1))    
            Break 
    }
    left := _left + (out ? 0 : offset)  
    top := _top + (out ? 0 : offset)
    Return 1
}
  
Esc:: ExitApp   
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

12

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

SIZE + RECT = 24 байта, а не 16.

13

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

typedef struct tagRECT
{
    LONG    left;
    LONG    top;
    LONG    right;
    LONG    bottom;
} RECT

Знаю, но какой смысл, если right и bottom нам не интересны.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

14

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Нам - не интересны. Но CalculatePopupWindowPosition об этом "не знает" и честно заполнит все 4 выходных параметра, выехав за пределы выделенной области. Какие данные при этом могут затереться, кто знает?

15

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Да, это ведь не AutoHotkey, где можно опускать ненужное. С WinAPI такие фокусы не пройдут.

16

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

То есть в таком варианте,  изменяются следующие 8 байт адресного пространства процесса,  отвечающих уже неизвестно за что?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

17

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Конечно. Функция ждёт указатель на 16 байт. И вы никак ей не скажете, что там для неё только 8.

18

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Небольшой пример. Под локальную переменную Test место в памяти выделяется вслед за structs. При многократном нажатии '1' и случайном перемещении курсора Test портится "лишними" данными. (win8.1 x86)

Gui, Margin, 5, 5
Gui, Font, Italic s34 cWhite, Times New Roman
Gui, +AlwaysOnTop +ToolWindow -0x00400000 +E0x08000020 -DPIScale +Lastfound +HWNDhGui  +Owner
Gui, Color, 2F4F4F 
WinSet, TransParent, 200

1:: 
    DllCall("DestroyWindow", "Ptr", hStatic)
    Gui Add, Text, hwndhStatic x5 y5, % "TickCount:`n" A_TickCount
    Gui, Show, % "NA AutoSize " (DllCall("IsWindowVisible", "uint", hGui) ? "" : "Hide") 
    If CalculatePopupWindowPosition(x, y, hGui, 25)
        Gui, Show, NA x%x% y%y% 
    Return 
    
2:: Gui, Hide

CalculatePopupWindowPosition(byref left, byref top, hwnd, offset = 0, x = "", y = "")  { 
    VarSetCapacity(POINT, 8, 0), VarSetCapacity(structs, 16, 0), VarSetCapacity(Test, 8, 0)
    If (x = "" || y = "")
        DllCall("GetCursorPos", "ptr", &POINT)
    Else
        NumPut(x, POINT, 0, "int"), NumPut(y, POINT, 4, "int")  
    DHW := A_DetectHiddenWindows
    DetectHiddenWindows, On
    WinGetPos, , , w, h, ahk_id %hwnd% 
    DetectHiddenWindows, %DHW%
    NumPut(w + offset, structs, 0, "int"), NumPut(h + offset, structs, 4, "int") ; SIZE   
    Loop 2
    {
        If !DllCall("CalculatePopupWindowPosition"
            , "ptr", &POINT
            , "ptr", &structs
            , "int", [0, 0x0008][A_Index]
            , "ptr", 0
            , "ptr", &structs + 8)
            Return 0 
        _left := NumGet(structs, 8, "int"), _top := NumGet(structs, 12, "int") 
        If !(_left < NumGet(POINT, 0, "int") && _top < NumGet(POINT, 4, "int")  && (out := 1))    
            Break 
    }
    left := _left + (out ? 0 : offset)  
    top := _top + (out ? 0 : offset)
    ListVars
    Return 1
}
  
Esc:: ExitApp   

19 (изменено: serzh82saratov, 2016-05-02 16:10:06)

Re: AHK: Позиционирование окна, в зависимости от позиции мыши

Всё таки оно как то некорректно работает с двумя мониторами, или я что то не понял. В принципе стандартный тултип тоже в таких случаях ошибается. Пытался например сделать, чтобы от исходной точки окно было слева и по высоте посередине, но при приближении к краям окно уходит за какой нибудь край (при разных попытках реализации).

Желаемое, оказалось было не сложно сделать встроенными методами, вроде ошибок нет:


#SingleInstance Force       
DetectHiddenWindows, On

Gui, Margin, 5, 5
Gui, Font, Italic s54 cWhite, Times New Roman
Gui, +AlwaysOnTop +ToolWindow -0x00400000 +E0x08000020 -DPIScale +Lastfound +HWNDhGui +Owner
Gui, Color, 2F4F4F 
WinSet, TransParent, 200

1::   
    DllCall("DestroyWindow", "Ptr", hStatic) 
    Gui Add, Text, hwndhStatic x5 y5, % " TickCount: `n " A_TickCount " "
    Gui, Show, % "NA AutoSize " (DllCall("IsWindowVisible", "uint", hGui) ? "" : "Hide")  
    WinGetPos, , , WinWidth, WinHeight, % "ahk_id" hGui 
    If CalculatePopupWindowPosition(X, Y, WinWidth, WinHeight, -WinWidth-45, -WinHeight//2) 
        Gui, Show, NA x%X% y%Y%
    Return

2:: Gui, Hide

CalculatePopupWindowPosition(byref left, byref top, w, h, offsetx = 0, offsety = 0, x = "", y = "")  {
    If (x = "" || y = "")
        DllCall("GetCursorPos", "int64P", pt), x := pt << 32 >> 32, y := pt >> 32
    SysGet, MonCount, MonitorCount
    Loop % MonCount
    {
        SysGet, m, Monitor, %A_Index%
        If (x >= mLeft && x <= mRight && y >= mTop && y <= mBottom)
            Break
        If (A_Index = MonCount)
            Return 0
    }
    left := x + offsetx + (offsetx > 0) * w < mLeft ? mLeft : x + offsetx + w > mRight ? mRight - w : x + offsetx
    top := y + offsety + (offsety > 0) * h < mTop ? mTop : y + offsety + h > mBottom ? mBottom - h : y + offsety
    Return 1
}

Но только стоит учитывать, что если указываются свои координаты показа, то они должны находится в пределах монитора.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui