SheridanCoriana6

Affinity my toolbarV2

Jan 7th, 2026
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Autohotkey 13.23 KB | Source Code | 0 0
  1. #Requires AutoHotkey v2.0
  2. #SingleInstance Force
  3.  
  4. ; --- Konfiguracja ---
  5. global ARTIFACT_NAME := "Affinity Keyboard"
  6. global AffinityExe := "Affinity.exe"
  7. global BTN_HEIGHT := 25, PADDING := 5
  8. global FONT_FAMILY := "Segoe UI"
  9. global IniFile := A_ScriptDir "\AffinityKeyboard_Settings.ini"
  10.  
  11. ; --- Zmienne Globalne GDI+ (Caching) ---
  12. global gdiplusToken := 0
  13. global hdcScreen := 0, hdcMem := 0, hbm := 0, pGraphics := 0
  14. global pFont := 0, pFormat := 0, pBrushText := 0
  15. global guiWidth := 0, guiHeight := 0
  16. global hoveredButtonIndex := 0
  17.  
  18. ; --- Wczytywanie ustawień ---
  19. global posX := IniRead(IniFile, "Position", "X", 200)
  20. global posY := IniRead(IniFile, "Position", "Y", 200)
  21.  
  22. ; --- Inicjalizacja GDI+ ---
  23. if !(gdiplusToken := Gdip_Startup()) {
  24.     MsgBox("Krytyczny błąd: Nie można uruchomić biblioteki GDI+!")
  25.     ExitApp
  26. }
  27.  
  28. ; --- Definicje przycisków ---
  29. global buttons := []
  30. buttons_data := [
  31.     {name:"New",     color:0xFF8BC34A, action:"^n"},
  32.     {name:"Open",    color:0xFF03A9F4, action:"^o"},
  33.     {name:"Copy",    color:0xFFFFC107, action:"^c"},
  34.     {name:"Paste",   color:0xFFFFEB3B, action:"^v"},
  35.     {name:"Undo",    color:0xFFFF7043, action:"^z"},
  36.     {name:"Redo",    color:0xFFE91E63, action:"^+z"},
  37.     {name:"Delete",  color:0xFF9E9E9E, action:"{Backspace}"},
  38.     {name:"Invert",  color:0xFFC47DD0, action:"^i"},
  39.     {name:"Fit",     color:0xFFADD8E6, action:"^0"},
  40.     {name:"[",       color:0xFFEBEBEB, action:"["},
  41.     {name:"]",       color:0xFFEBEBEB, action:"]"},
  42.     {name:"Merge.S", color:0xFF32FD53, action:"^+e"},
  43.     {name:"Merge.V", color:0xFF2BE6FF, action:"^!+e"}, 
  44.     {name:"Duplicate", color:0xFFFFA0F0, action:"^j"},
  45.     {name:"Exp2JPG", color:0xFFFFEB3B, action:"^!+w"}
  46. ]
  47.  
  48. ; --- Oblicz rozmiar czcionki ---
  49. longest_name := ""
  50. for _, btn_data in buttons_data {
  51.     if StrLen(btn_data.name) > StrLen(longest_name)
  52.         longest_name := btn_data.name
  53. }
  54.  
  55. ; Oblicz max rozmiar czcionki (targetW=100)
  56. global maxFontSize := CalculateMaxFontSize(FONT_FAMILY, longest_name, 100, BTN_HEIGHT, 8)
  57.  
  58. ; Inicjalizacja pędzla i czcionki (Caching)
  59. pFontFamily := Gdip_FontFamilyCreate(FONT_FAMILY)
  60. pFont := Gdip_FontCreate(pFontFamily, maxFontSize, 1)
  61. pFormat := Gdip_StringFormatCreate()
  62. Gdip_StringFormatSetAlign(pFormat, 1)
  63. Gdip_StringFormatSetLineAlign(pFormat, 1)
  64. pBrushText := Gdip_BrushCreateSolid(0xFF000000)
  65. Gdip_DeleteFontFamily(pFontFamily)
  66.  
  67. x := PADDING
  68. for _, btn_data in buttons_data {
  69.     textWidth := MeasureTextWidth(btn_data.name, maxFontSize, FONT_FAMILY)
  70.     nameLength := StrLen(btn_data.name)
  71.     charPadding := (nameLength > 0) ? (textWidth / nameLength) : MeasureTextWidth("M", maxFontSize, FONT_FAMILY)
  72.     btn_width := Round(textWidth + (2 * charPadding))
  73.  
  74.     btn_data.x := x, btn_data.y := PADDING, btn_data.w := btn_width, btn_data.h := BTN_HEIGHT
  75.     buttons.Push(btn_data)
  76.     x += btn_width + PADDING
  77. }
  78. ; Przycisk wyjścia
  79. buttons.Push({name: "X", color: 0xFFF44336, action: "ExitApp", x: x + 10, y: PADDING, w: 25, h: 25})
  80.  
  81. lastBtn := buttons[buttons.Length]
  82. guiWidth := lastBtn.x + lastBtn.w + PADDING
  83. guiHeight := BTN_HEIGHT + PADDING * 2
  84.  
  85. ; --- Tworzenie GUI (Layered Window) ---
  86. MyGui := Gui("+AlwaysOnTop +ToolWindow -Caption +E0x80000") ; E0x80000 = WS_EX_LAYERED
  87. MyGui.OnEvent("Close", CleanupAndExit)
  88.  
  89. ; Przygotuj bufory GDI+ (DIB Section dla Layered Window)
  90. hdcScreen := DllCall("GetDC", "ptr", 0, "ptr")
  91. hdcMem := DllCall("CreateCompatibleDC", "ptr", hdcScreen, "ptr")
  92. hbm := CreateDIBSection(guiWidth, guiHeight)
  93. obm := DllCall("SelectObject", "ptr", hdcMem, "ptr", hbm, "ptr")
  94. pGraphics := Gdip_GraphicsFromHDC(hdcMem)
  95. Gdip_SetSmoothingMode(pGraphics, 4)
  96.  
  97. ; Wspieranie przesuwania i komunikatów
  98. OnMessage(0x201, WM_LBUTTONDOWN)
  99. OnMessage(0x200, WM_MOUSEMOVE)
  100.  
  101. UpdateUI()
  102. MyGui.Show("x" posX " y" posY " w" guiWidth " h" guiHeight " NA")
  103. return
  104.  
  105. ; === GŁÓWNE FUNKCJE ===
  106.  
  107. UpdateUI() {
  108.     global MyGui, pGraphics, hbm, hdcMem, hdcScreen, guiWidth, guiHeight, hoveredButtonIndex, buttons
  109.     global pFont, pFormat, pBrushText
  110.  
  111.     try {
  112.         Gdip_GraphicsClear(pGraphics, 0x00000000) ; Przezroczyste tło
  113.        
  114.         ; Tło paska (ciemne)
  115.         pBrushMainBG := Gdip_BrushCreateSolid(0xFF404040)
  116.         Gdip_FillRectangle(pGraphics, pBrushMainBG, 0, 0, guiWidth, guiHeight)
  117.         Gdip_DeleteBrush(pBrushMainBG)
  118.  
  119.         for i, btn in buttons {
  120.             color := btn.color
  121.             if (i == hoveredButtonIndex) {
  122.                 ; Hover effect: lighter/dimmed
  123.                 color := (color & 0x00FFFFFF) | 0xB3000000
  124.             }
  125.            
  126.             pBrushBG := Gdip_BrushCreateSolid(color)
  127.             Gdip_FillRectangle(pGraphics, pBrushBG, btn.x, btn.y, btn.w, btn.h)
  128.             Gdip_DrawString(pGraphics, btn.name, pFont, pFormat, pBrushText, btn.x, btn.y, btn.w, btn.h)
  129.             Gdip_DeleteBrush(pBrushBG)
  130.         }
  131.  
  132.         ; Odśwież okno warstwowe
  133.         UpdateLayeredWindow(MyGui.Hwnd, hdcMem, hdcScreen, guiWidth, guiHeight)
  134.     } catch Error as err {
  135.         ; Cichy błąd, żeby nie blokował UI
  136.         OutputDebug("Redraw Error: " err.Message)
  137.     }
  138. }
  139.  
  140. WM_MOUSEMOVE(wParam, lParam, msg, hwnd) {
  141.     Critical
  142.     global MyGui, buttons, hoveredButtonIndex
  143.     if (hwnd != MyGui.Hwnd)
  144.         return
  145.  
  146.     x := lParam & 0xFFFF
  147.     y := (lParam >> 16) & 0xFFFF
  148.    
  149.     currentlyHovered := 0
  150.     for i, btn in buttons {
  151.         if (x >= btn.x and x <= btn.x + btn.w and y >= btn.y and y <= btn.y + btn.h) {
  152.             currentlyHovered := i
  153.             break
  154.         }
  155.     }
  156.  
  157.     if (currentlyHovered != hoveredButtonIndex) {
  158.         hoveredButtonIndex := currentlyHovered
  159.         UpdateUI()
  160.     }
  161. }
  162.  
  163. WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) {
  164.     Critical
  165.     global MyGui, buttons, IniFile, posX, posY
  166.     if (hwnd != MyGui.Hwnd)
  167.         return
  168.  
  169.     x := lParam & 0xFFFF
  170.     y := (lParam >> 16) & 0xFFFF
  171.    
  172.     for _, btn in buttons {
  173.         if (x >= btn.x and x <= btn.x + btn.w and y >= btn.y and y <= btn.y + btn.h) {
  174.             if (btn.action = "ExitApp") {
  175.                 CleanupAndExit()
  176.             } else {
  177.                 SendToAffinity(btn.action)
  178.             }
  179.             return
  180.         }
  181.     }
  182.     PostMessage(0xA1, 2, , , "A") ; Drag window
  183. }
  184.  
  185. SendToAffinity(shortcut) {
  186.     global AffinityExe
  187.     if WinExist("ahk_exe " AffinityExe) {
  188.         try {
  189.             WinActivate("ahk_exe " AffinityExe)
  190.             if WinActive("ahk_exe " AffinityExe)
  191.                 Send(shortcut)
  192.         } catch Error as err {
  193.             TrayTip("Błąd wysyłania: " err.Message, ARTIFACT_NAME)
  194.         }
  195.     } else {
  196.         TrayTip("Nie można znaleźć procesu " AffinityExe, ARTIFACT_NAME, 2)
  197.     }
  198. }
  199.  
  200. CleanupAndExit(*) {
  201.     global MyGui, IniFile, gdiplusToken
  202.     global hdcScreen, hdcMem, hbm, pGraphics, pFont, pFormat, pBrushText
  203.  
  204.     ; Zapisz pozycję
  205.     try {
  206.         WinGetPos(&px, &py, , , MyGui.Hwnd)
  207.         IniWrite(px, IniFile, "Position", "X")
  208.         IniWrite(py, IniFile, "Position", "Y")
  209.     }
  210.    
  211.     ; Zwolnij zasoby
  212.     Gdip_DeleteGraphics(pGraphics)
  213.     DllCall("SelectObject", "ptr", hdcMem, "ptr", obm)
  214.     DllCall("DeleteObject", "ptr", hbm)
  215.     DllCall("DeleteDC", "ptr", hdcMem)
  216.     DllCall("ReleaseDC", "ptr", 0, "ptr", hdcScreen)
  217.    
  218.     Gdip_DeleteFont(pFont)
  219.     Gdip_DeleteStringFormat(pFormat)
  220.     Gdip_DeleteBrush(pBrushText)
  221.    
  222.     Gdip_Shutdown(gdiplusToken)
  223.     ExitApp
  224. }
  225.  
  226. ; --- POMOCNICZE FUNKCJE GDI+ ---
  227.  
  228. MeasureTextWidth(text, fontSize, fontFamily) {
  229.     hdc := DllCall("GetDC", "ptr", 0)
  230.     pGraphics := Gdip_GraphicsFromHDC(hdc)
  231.     pFamilyObj := Gdip_FontFamilyCreate(fontFamily)
  232.     pFont := Gdip_FontCreate(pFamilyObj, fontSize, 1)
  233.    
  234.     layoutRect := Buffer(16), NumPut("float", 0, "float", 0, "float", 1000, "float", 100, layoutRect)
  235.     boundingBox := Buffer(16)
  236.     Gdip_MeasureString(pGraphics, text, pFont, layoutRect, 0, boundingBox)
  237.     measuredW := NumGet(boundingBox, 8, "float")
  238.    
  239.     Gdip_DeleteFont(pFont)
  240.     Gdip_DeleteFontFamily(pFamilyObj)
  241.     Gdip_DeleteGraphics(pGraphics)
  242.     DllCall("ReleaseDC", "ptr", 0, "ptr", hdc)
  243.     return measuredW
  244. }
  245.  
  246. CalculateMaxFontSize(fontFamily, textToMeasure, targetW, targetH, textPadding) {
  247.     hdc := DllCall("GetDC", "ptr", 0)
  248.     pg := Gdip_GraphicsFromHDC(hdc)
  249.     pf := Gdip_FontFamilyCreate(fontFamily)
  250.     lr := Buffer(16), NumPut("float", 0, "float", 0, "float", targetW, "float", targetH, lr)
  251.     bb := Buffer(16)
  252.  
  253.     size := 16
  254.     while (size >= 4) {
  255.         f := Gdip_FontCreate(pf, size, 1)
  256.         Gdip_MeasureString(pg, textToMeasure, f, lr, 0, bb)
  257.         w := NumGet(bb, 8, "float")
  258.         h := NumGet(bb, 12, "float")
  259.         Gdip_DeleteFont(f)
  260.         if (w < targetW - textPadding && h < targetH) {
  261.             Gdip_DeleteFontFamily(pf)
  262.             Gdip_DeleteGraphics(pg)
  263.             DllCall("ReleaseDC", "ptr", 0, "ptr", hdc)
  264.             return size
  265.         }
  266.         size -= 0.5
  267.     }
  268.     Gdip_DeleteFontFamily(pf)
  269.     Gdip_DeleteGraphics(pg)
  270.     DllCall("ReleaseDC", "ptr", 0, "ptr", hdc)
  271.     return 8
  272. }
  273.  
  274. UpdateLayeredWindow(hwnd, hdcMem, hdcScreen, w, h) {
  275.     DllCall("UpdateLayeredWindow", "ptr", hwnd, "ptr", hdcScreen, "ptr", 0, "int64*", w | (h << 32), "ptr", hdcMem, "int64*", 0, "uint", 0, "int*", 0xFF << 16 | 1 << 24, "uint", 2)
  276. }
  277.  
  278. CreateDIBSection(w, h, hdc := 0) {
  279.     hdc := hdc ? hdc : DllCall("GetDC", "ptr", 0, "ptr")
  280.     bi := Buffer(40, 0)
  281.     NumPut("uint", 40, bi, 0)
  282.     NumPut("int", w, bi, 4)
  283.     NumPut("int", -h, bi, 8)
  284.     NumPut("ushort", 1, bi, 12)
  285.     NumPut("ushort", 32, bi, 14)
  286.     NumPut("uint", 0, bi, 16)
  287.    
  288.     hbm := DllCall("CreateDIBSection", "ptr", hdc, "ptr", bi, "uint", 0, "ptr*", 0, "ptr", 0, "uint", 0, "ptr")
  289.     if !hdc
  290.         DllCall("ReleaseDC", "ptr", 0, "ptr", hdc)
  291.     return hbm
  292. }
  293.  
  294. ; --- BIBLIOTEKA GDI+ (Zoptymalizowana pod v2) ---
  295. Gdip_Startup() {
  296.     if !DllCall("GetModuleHandle", "str", "gdiplus", "ptr")
  297.         DllCall("LoadLibrary", "str", "gdiplus")
  298.     pToken := Buffer(A_PtrSize)
  299.     si := Buffer(24, 0), NumPut("int", 1, si)
  300.     if DllCall("gdiplus\GdiplusStartup", "ptr", pToken, "ptr", si, "ptr", 0)
  301.         return 0
  302.     return NumGet(pToken, "ptr")
  303. }
  304. Gdip_Shutdown(pToken) => DllCall("gdiplus\GdiplusShutdown", "ptr", pToken)
  305. Gdip_GraphicsFromHDC(hdc) {
  306.     pGraphics := Buffer(A_PtrSize)
  307.     DllCall("gdiplus\GdipCreateFromHDC", "ptr", hdc, "ptr", pGraphics)
  308.     return NumGet(pGraphics, "ptr")
  309. }
  310. Gdip_GraphicsFromImage(hbm) {
  311.     pGraphics := Buffer(A_PtrSize)
  312.     DllCall("gdiplus\GdipGetImageGraphicsContext", "ptr", hbm, "ptr", pGraphics)
  313.     return NumGet(pGraphics, "ptr")
  314. }
  315. Gdip_CreateBitmap(w, h) {
  316.     pBitmap := Buffer(A_PtrSize)
  317.     DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", w, "int", h, "int", 0, "int", 0x26200A, "ptr", 0, "ptr", pBitmap)
  318.     return NumGet(pBitmap, "ptr")
  319. }
  320. Gdip_GraphicsClear(pGraphics, color := 0) => DllCall("gdiplus\GdipGraphicsClear", "ptr", pGraphics, "uint", color)
  321. Gdip_DeleteGraphics(pGraphics) => DllCall("gdiplus\GdipDeleteGraphics", "ptr", pGraphics)
  322. Gdip_DisposeImage(pBitmap) => DllCall("gdiplus\GdipDisposeImage", "ptr", pBitmap)
  323. Gdip_SetSmoothingMode(pGraphics, mode) => DllCall("gdiplus\GdipSetSmoothingMode", "ptr", pGraphics, "int", mode)
  324. Gdip_BrushCreateSolid(color) {
  325.     pBrush := Buffer(A_PtrSize)
  326.     DllCall("gdiplus\GdipCreateSolidFill", "uint", color, "ptr", pBrush)
  327.     return NumGet(pBrush, "ptr")
  328. }
  329. Gdip_DeleteBrush(pBrush) => DllCall("gdiplus\GdipDeleteBrush", "ptr", pBrush)
  330. Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h) => DllCall("gdiplus\GdipFillRectangle", "ptr", pGraphics, "ptr", pBrush, "float", x, "float", y, "float", w, "float", h)
  331. Gdip_StringFormatCreate() {
  332.     pFormat := Buffer(A_PtrSize)
  333.     DllCall("gdiplus\GdipCreateStringFormat", "int", 0, "int", 0, "ptr", pFormat)
  334.     return NumGet(pFormat, "ptr")
  335. }
  336. Gdip_DeleteStringFormat(pFormat) => DllCall("gdiplus\GdipDeleteStringFormat", "ptr", pFormat)
  337. Gdip_StringFormatSetAlign(pFormat, align) => DllCall("gdiplus\GdipSetStringFormatAlign", "ptr", pFormat, "int", align)
  338. Gdip_StringFormatSetLineAlign(pFormat, align) => DllCall("gdiplus\GdipSetStringFormatLineAlign", "ptr", pFormat, "int", align)
  339. Gdip_DrawString(pGraphics, s, pFont, pFormat, pBrush, x, y, w, h) {
  340.     r := Buffer(16), NumPut("float", x, "float", y, "float", w, "float", h, r)
  341.     DllCall("gdiplus\GdipDrawString", "ptr", pGraphics, "str", s, "int", -1, "ptr", pFont, "ptr", r, "ptr", pFormat, "ptr", pBrush)
  342. }
  343. Gdip_FontFamilyCreate(sFamily) {
  344.     pFamily := Buffer(A_PtrSize)
  345.     if DllCall("gdiplus\GdipCreateFontFamilyFromName", "str", sFamily, "ptr", 0, "ptr", pFamily)
  346.         return 0
  347.     return NumGet(pFamily, "ptr")
  348. }
  349. Gdip_DeleteFontFamily(pFamily) => DllCall("gdiplus\GdipDeleteFontFamily", "ptr", pFamily)
  350. Gdip_FontCreate(pFamily, nSize, nStyle := 0) {
  351.     pFont := Buffer(A_PtrSize)
  352.     DllCall("gdiplus\GdipCreateFont", "ptr", pFamily, "float", nSize, "int", nStyle, "int", 2, "ptr", pFont)
  353.     return NumGet(pFont, "ptr")
  354. }
  355. Gdip_DeleteFont(pFont) => DllCall("gdiplus\GdipDeleteFont", "ptr", pFont)
  356. Gdip_MeasureString(pGraphics, s, pFont, pLayoutRect, pFormat, pBoundingBox) {
  357.     DllCall("gdiplus\GdipMeasureString", "ptr", pGraphics, "str", s, "int", -1, "ptr", pFont, "ptr", pLayoutRect, "ptr", pFormat, "ptr", pBoundingBox, "ptr*", 0, "ptr*", 0)
  358. }
  359.  
Tags: Affinity
Advertisement
Add Comment
Please, Sign In to add comment