Presentation describes creating very simple message box, with customizable font (this goes to Laszlo).
No GUI commands are used, and very little effort is needed to extended it to support for instance hyperlink (SySLink instead Static) more buttons, images etc... i.e. to recreate classic MsgBox just more customizable.
U can use this as basis for some other work, even custom controls can be created, with the very same look and feel like those contained in various dll's around (they will be slower, ofcourse, but no dll's will be required)
Script registers its own window class - MM_AHKMsgBox - and that you can see with Window Spy.
Finaly, possibility of Msg interacting with AHK Guis is 0, its true black box. U can create 1000 GUIs without having to worry about 99 Guis limitation of AHK.
Notes
[*:3aygez43] U may notice icon becomes "falling sand" on the start. This can be solved by explicitely setting cursor in RegisterClass but I was to lazy to do that
[*:3aygez43] Some cleaning should be done, but that was not the point of this tut.
[*:3aygez43] Script is kinda big for this simple task, but in true API world, even Hello World appears to be very complex.
#Persistent #SingleInstance, force str = (LTrim Volume in drive C has no label. Volume Serial Number is B857-7430 Directory of C:\Documents and Settings\mmilic 07.09.2007 16:18 <DIR> . 07.09.2007 16:18 <DIR> .. 07.09.2007 10:12 <DIR> Desktop 19.01.2007 16:01 <DIR> Favorites 28.08.2007 15:28 <DIR> My Documents 07.09.2007 16:18 532 out 14.02.2007 16:57 <DIR> Start Menu 1 File(s) 532 bytes 6 Dir(s) 180.445.904.896 bytes free ) Msg(str, "s10, Courier New") return Msg(str, font) { global static init=0 if (!init++) Msg_RegisterClass() msg_str := str, msg_font := font hwnd := Msg_CreateWindow() SysGet, d, 31 WinMove, ahk_id %hwnd%,, 100,100,w+40,h+d+80 } Msg_WndProc(hwnd, uMsg, wParam, lParam) { global static WS_VISIBLE=0x10000000, WS_CHILD=0x40000000, WS_CLIPCHILDREN=0x2000000 if (uMsg = 1) { GetTextSize(msg_str, msg_font, w, h) hCtrl := API_CreateWindowEx(0,"Static", msg_str, WS_CHILD | WS_VISIBLE ,0,0,w,h ,hwnd, 0, 0, 0) hFont := CreateFont(msg_font) SendMessage, 0x30, %hFont%, 1,, ahk_id %hCtrl% ;WM_SETFONT = 0x30 hCtrl := API_CreateWindowEx(0,"Button", "OK", WS_CHILD | WS_VISIBLE ,10,h+30,50,25 ,hwnd, 101, 0, 0) } if (uMsg=0x111) { ;the only command is now bn_clicked so .... DllCall("DestroyWindow", "uint", hwnd) } return, DllCall("DefWindowProc", "uint", hwnd, "uint", umsg, "uint", wParam, "uint", lParam) } Msg_CreateWindow(){ static WS_VISIBLE=0x10000000, WS_CLIPCHILDREN=0x2000000, WS_SYSMENU=0x80000,WS_MINIMIZEBOX=0x20000,WS_MAXIMIZEBOX=0x10000 return API_CreateWindowEx(1, "MM_AHKMsgBox", A_ScriptName, WS_VISIBLE | WS_SYSMENU ,0,0,0,0, 0,0,0,0) } Msg_RegisterClass(){ cName := "MM_AHKMsgBox" WndProc := RegisterCallback("Msg_WndProc", "F") VarSetCapacity(WC, 40, 0) NumPut(3, WC, 0) NumPut(WndProc, WC, 4) NumPut(0, WC, 8) ;reserve NumPut(0, WC, 12) ;reserve NumPut(0, WC, 16) ;instance NumPut(0, WC, 20) ;icon NumPut(0, WC, 24) ;curcors ;put some cursor here NumPut(16, WC, 28) ;background NumPut(0, WC, 32) ;menu NumPut(&cName, WC, 36) ;class return DllCall("RegisterClass", "uint", &WC) } ;-------------------------------------------------------------------------- ; Function: CreateFont ; Creates font in memory which can be used with any API function accepting font handles. ; ; Parameters: ; pFont - AHK font description, "style, face" ; ; Returns: ; Font handle ; ; Example: ;> hFont := CreateFont("s12 italic, Courier New") ;> SendMessage, 0x30, %hFont%, 1,, ahk_id %hGuiControl% ;WM_SETFONT = 0x30 CreateFont(pFont="") { ;parse font italic := InStr(pFont, "italic") ? 1 : 0 underline := InStr(pFont, "underline") ? 1 : 0 strikeout := InStr(pFont, "strikeout") ? 1 : 0 weight := InStr(pFont, "bold") ? 700 : 400 ;height RegExMatch(pFont, "(?<=[S|s])(\d{1,2})(?=[ ,])", height) if (height = "") height := 10 RegRead, LogPixels, HKEY_LOCAL_MACHINE, SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontDPI, LogPixels height := -DllCall("MulDiv", "int", Height, "int", LogPixels, "int", 72) ;face RegExMatch(pFont, "(?<=,).+", fontFace) if (fontFace != "") fontFace := RegExReplace( fontFace, "(^\s*)|(\s*$)") ;trim else fontFace := "MS Sans Serif" ;create font hFont := DllCall("CreateFont", "int", height, "int", 0, "int", 0, "int", 0 ,"int", weight, "Uint", italic, "Uint", underline ,"uint", strikeOut, "Uint", nCharSet, "Uint", 0, "Uint", 0, "Uint", 0, "Uint", 0, "str", fontFace) return hFont } ;----------------------------------------------------------------------------------------------------------------------- ; Function: GetTextSize ; Calculate widht and/or height of text. ; Font face, style and number of lines is taken into account ;: ; <By.majkinetor> ; ; Parameters: ; pStr - Text to be measured ; pFont - Font description in AHK syntax, default size is 10, default font is MS Sans Serif ; pHeight - Set to true to return height also. False is default. ; pAdd - Number to add on width and height. ; ; Returns: ; Text width if pHeight=false. Otherwise, dimension is returned as "width,height" ; ; Dependencies: ; <ExtractInteger> ; ; Examples: ; width := GetTextSize("string to be measured", "bold s22, Courier New" ) ; GetTextSize(pStr, pFont, ByRef w, ByRef h) { local height, weight, italic, underline, strikeout , nCharSet local hdc := DllCall("GetDC", "Uint", 0) local hFont, hOldFont local resW, resH, SIZE hFont := CreateFont( pFont ) hOldFont := DllCall("SelectObject", "Uint", hDC, "Uint", hFont) VarSetCapacity(SIZE, 16) curW=0 Loop, parse, pStr, `n { DllCall("DrawTextA", "Uint", hDC, "str", A_LoopField, "int", StrLen(pStr), "uint", &SIZE, "uint", 0x400) resW := NumGet(SIZE, 8) curW := resW > curW ? resW : curW } DllCall("DrawTextA", "Uint", hDC, "str", pStr, "int", StrLen(pStr), "uint", &SIZE, "uint", 0x400) ;clean DllCall("SelectObject", "Uint", hDC, "Uint", hOldFont) DllCall("DeleteObject", "Uint", hFont) DllCall("ReleaseDC", "Uint", 0, "Uint", hDC) w := NumGet(SIZE, 8), h := NumGet(SIZE, 12) return 1 } API_CreateWindowEx(dwExStyle,lpClassName,lpWindowName,dwStyle,x,y,nWidth,nHeight,hWndParent,hMenu,hInstance,lpParam){ return DllCall("CreateWindowEx" , "Uint", dwExStyle , "str", lpClassName , "str", lpWindowName , "Uint", dwStyle , "int", x , "int", y , "int", nWidth , "int", nHeight , "Uint", hWndParent , "Uint", hMenu , "Uint", hInstance , "Uint", lpParam) }
