Win API: Add a control to an unowned application
Posted: Mon Jun 11, 2007 7:51 pm
Just a little timewaster for a Monday afternoon. You can't directly add a PureBasic gadget to an application not owned by your thread, however using API it can be managed within certain limits. The main limitation is that you can't get the events of the application's existing controls, but in a lot of cases you don't really need them. Here's a small example that adds a PI button to the Windows Calculator. It resizes the CLEAR button smaller to make room first. A PI button is already on the Scientific view, so the one added here is an extra one if you're using that view.
Note that if the window name of your calculator is not "Calculator" you will have to modify this code slightly to reflect the name yours is using.
Also, it'll look best if you check "XP Skin Support" in the Compiler Options.
Note that if the window name of your calculator is not "Calculator" you will have to modify this code slightly to reflect the name yours is using.
Also, it'll look best if you check "XP Skin Support" in the Compiler Options.
Code: Select all
;==========================================================================
; Program: Add a functional button to the Windows Calculator
; Author: netmaestro
; Date: June 11, 2007
; Target Compiler: PureBasic 4.0 and later
; Target OS: Microsoft Windows XP Only
;==========================================================================
Global oldproc, quit=0, cebutton, clearbutton, one, two, three
Global four, five, six, seven, eight, nine, zero, point
Procedure ButtonProc(hwnd, msg, wParam, lParam)
Select msg
Case #WM_NCDESTROY
End
Case #WM_LBUTTONUP
SendMessage_(cebutton, #BM_CLICK, 0,0)
SendMessage_(three, #BM_CLICK, 0,0)
SendMessage_(point, #BM_CLICK, 0,0)
SendMessage_(one, #BM_CLICK, 0,0)
SendMessage_(four, #BM_CLICK, 0,0)
SendMessage_(one, #BM_CLICK, 0,0)
SendMessage_(five, #BM_CLICK, 0,0)
EndSelect
ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wParam, lParam)
EndProcedure
Procedure GetClearButtons(hwnd, param)
wt.s = Space(10)
SendMessage_(hwnd, #WM_GETTEXT, 10, @wt)
If wt = "C"
clearbutton = hwnd
ElseIf wt = "CE"
cebutton = hwnd
EndIf
ProcedureReturn 1
EndProcedure
Procedure GetNumbers(hwnd, param)
wt.s = Space(10)
SendMessage_(hwnd, #WM_GETTEXT, 10, @wt)
Select wt
Case "1" : one = hwnd
Case "2" : two = hwnd
Case "3" : three = hwnd
Case "4" : four = hwnd
Case "5" : five = hwnd
Case "6" : six = hwnd
Case "7" : seven = hwnd
Case "8" : eight = hwnd
Case "9" : nine = hwnd
Case "0" : zero = hwnd
Case "." : point = hwnd
EndSelect
ProcedureReturn 1
EndProcedure
RunProgram("calc.exe")
start = ElapsedMilliseconds()
Repeat
c = FindWindow_(0, "Calculator")
Delay(1)
Until c Or ElapsedMilliseconds()-start > 500
If c
EnumChildWindows_(c, @GetClearButtons(), 0)
EnumChildWindows_(c, @GetNumbers(), 0)
SetWindowPos_(clearbutton, 0,0,0,28,29,#SWP_NOZORDER|#SWP_NOMOVE|#SWP_FRAMECHANGED)
InitCommonControls_()
GetWindowRect_(c, @cr.RECT)
w = cr\right-cr\left
If w > 270 ; Scientific
button = CreateWindowEx_(0,"Button", "PI", #WS_CHILD|#WS_VISIBLE,432,62,28,29,c,0,GetModuleHandle_(0),0)
Else ; Standard
button = CreateWindowEx_(0,"Button", "PI", #WS_CHILD|#WS_VISIBLE,216,37,28,29,c,0,GetModuleHandle_(0),0)
EndIf
Else
MessageRequester("OOPS!", "Can't find the Calculator!", #MB_ICONERROR)
End
EndIf
oldproc = SetWindowLong_(button, #GWL_WNDPROC, @ButtonProc())
result = GetMessage_(@msg.MSG, #Null, #Null, #Null)
While result <> 0
If result = -1 ; GetMessage failed
MessageRequester("OOPS!", "Failure in GetMessage Loop", #MB_ICONERROR)
End
EndIf
TranslateMessage_(msg)
DispatchMessage_(msg)
result = GetMessage_(@msg.MSG, #Null, #Null, #Null)
Wend