XREA.COM Logo XREA.COM Ad

旧雑記サルベージ

94管理人 ★:06/09/06 17:41 ID:???
2006年01月26日
■AutoHotkeyで"タスクトレイに最小化"

AutoHotkeyでは、タスクトレイアイコンは通常一つだけしか持てない。
しかし、Shell_NotfyIconというAPI関数を使えばアイコンを作成できる。
作成したアイコンを操作すると、アイコン作成時に関連づけたウィンドウに指定した番号のメッセージが送られ、作成時に指定したアイコンIDと操作の内容が通知される。
これをOnMessageで捉えて、アイコンIDや操作に応じた動作を行えばよい。

とりあえず、このあいだのタイトルバーをホイールクリックする奴と、その前のウィンドウのアイコンを取得する奴と合わせて、タイトルバーをホイールクリックすると擬似的にタスクトレイに格納するというのを作ってみた。
格納したウィンドウは、トレイアイコンの何らかのクリック動作で復元される。
右クリックではメニューを出すようにしようかと思ったが、「復元」以外にコマンドが要らない気がするのでやめた。
プログラムが終了するときには自動的にすべてのアイコンを復元するようにした。

ホイールクリックのホットキーでは、MButtonをMButton upにし、カーソル下のウィンドウがアクティブかどうかをチェックする動作を加えた。
これにより、タイトルバー上でホイールを押し下げた後、タイトルバー外までカーソルを移動してから放すことで、キャンセルが行えるようになった。
クリック系の動作としてはこれが望ましい。

Shell_NotfyIconでは、いちいち構造体で情報を与えてやらないとならない。
Shell32.dllのバージョンによっては拡張機能が利用できるらしいが、とりあえず一番古くて簡単な奴を使うことにした。
なぜか操作を通知するメッセージの番号が指定できるようになっている。
AutoHotkeyのアイコンでは0x404が使われているようだが、標準アイコンの操作イベントはどうでもいいので、別の番号を指定して自分で作成したアイコンの分だけをOnMessageで捉えるようにした。

操作通知メッセージのlParamで通知される操作内容の番号の意味が載っている資料がなかった。
第1ビットがマウスボタンの押し上げフラグかと思ったが、違うらしい。
とりあえず、
0x200がカーソルが通過した
0x201:左ボタンを押した
0x202:左ボタンを放した
0x203:左ダブルクリック
0x204:右ボタンを押した
0x205:右ボタンを放した
0x206:右ダブルクリック
0x207:中ボタンを押した
0x208:中ボタンを放した
0x209:中ダブルクリック
までは調べた。
第4,5ボタンは利かないっぽい。
なんで0x200番からなのかはよくわからん。

CreateStruct(size)
{
    return DllCall("GlobalAlloc",UInt,0,UInt,size,UInt)
}
DestroyStruct(pStruct){
    DllCall("GlobalFree",UInt,pStruct,UInt)
}
StructSetInt(pStruct,offset,val){
    DllCall("RtlMoveMemory", UInt,pStruct+offset, UIntP,val, Int,4)
}
StructSetStr(pStruct,offset,val){
    DllCall("RtlMoveMemory", UInt,pStruct+offset, Str,val, Int,StrLen(val)+1)
}

numTrayIcon=0
Process,Exist
pid:=ErrorLevel
DetectHiddenWindows,On
WinGet,myhwnd,id,ahk_pid %pid% ahk_class AutoHotkey
DetectHiddenWindows,Off

OnMessage(0x405,"OnTrayIconEvent")
OnExit,RestoreFromTrayAll
return

GetWindowIcon(hwnd){
    i:=DllCall("GetClassLong",UInt,hwnd,Int,-34)
    if(i=0)
    {
        i:=DllCall("SendMessage",UInt,hwnd,UInt,0x7F,UInt,0,UInt,0,UInt)
        if(i=0)
        {
            i:=DllCall("SendMessage",UInt,hwnd,UInt,0x7F,UInt,1,UInt,0,UInt)
        }
    }
    return i
}

;引数にアイコンハンドルを指定
;自動的にIDが割り振られて返される
CreateTrayIcon(hicon,tooltip){
    global numTrayIcon,myhwnd
    ret=0
    StringLeft,tooltip,tooltip,63
    pnid:=CreateStruct(88)
    StructSetInt(pnid,0,88)
    StructSetInt(pnid,4,myhwnd)
    StructSetInt(pnid,8,11+numTrayIcon)
    StructSetInt(pnid,12,7)
    StructSetInt(pnid,16,0x405)
    StructSetInt(pnid,20,hicon)
    StructSetStr(pnid,24,tooltip)
    if(DllCall("Shell32.dll\Shell_NotifyIcon",UInt,0,UInt,pnid,UInt)){
        numTrayIcon++
        ret:=numTrayIcon
    }
    DestroyStruct(pnid)
    return ret
}
;引数にIDを指定
DeleteTrayIcon(id){
    global myhwnd
    pnid:=CreateStruct(88)
    StructSetInt(pnid,0,88)
    StructSetInt(pnid,4,myhwnd)
    StructSetInt(pnid,8,10+id)
    ret=0
    if(DllCall("Shell32.dll\Shell_NotifyIcon",UInt,2,UInt,pnid,UInt)){
        ret=1
    }
    DestroyStruct(pnid)
    return ret
}
MinimizeToTray(hwnd){
    global
    local t,ti
    WinGetTitle,t,ahk_id %hwnd%
    ti:=CreateTrayIcon(GetWindowIcon(hwnd),t)
    TrayIcon%ti%:=hwnd
    WinHide,ahk_id %hwnd%
}
RestoreFromTray(id,activate=1){
    global
    local hwnd
    hwnd:=TrayIcon%id%
    if(hwnd!=0){
        DeleteTrayIcon(id)
        WinShow,ahk_id %hwnd%
        if(activate){
            WinActivate,ahk_id %hwnd%
        }
        TrayIcon%id%:=0
    }
}
OnTrayIconEvent(w,l,m,h){
    ;マウスボタンが放されたとき解放
    if(l=0x202||l=0x205||l=0x20a){
        RestoreFromTray(w-10)
    }
}

RestoreFromTrayAll:
    Loop,%numTrayIcon%{
        RestoreFromTray(A_Index,0)
    }
    ExitApp
return

~MButton up::
    CoordMode,Mouse,Screen
    MouseGetPos, x, y, h
    If(WinActive("ahk_id " . h) && DllCall("SendMessage",UInt,h,UInt,0x84,UInt,0,UInt,x | y <<16,UInt)=2){
        MinimizeToTray(h)
    }
return
131KB
名前: E-mail:
ファイル:
0ch BBS 2005-10-08