This is more or less the way that plugins works in winamp.
The SDK dont provide a direct way to add buttons or menu tiems, so you need to do more or less this same thing.
To avoid that all crashes when user close winamp you need to detect when user is closing and take out your process from the queue.
Win API: Add a control to an unowned application
- Michael Vogel
- Addict
- Posts: 2797
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Hey - what a cool idea!
just bad, that the content of elements from other applications can't be read (at least in Win 2k).
I did just two more modifications...
* Case #WM_NCDESTROY,#WM_DESTROY
so Alt-F4 will also close the program now...
* GetWindowRect_(WinHandle,@winrect) [...]
put the new button to the left side now, the position seems to be not very accurate...
Michael
just bad, that the content of elements from other applications can't be read (at least in Win 2k).
I did just two more modifications...
* Case #WM_NCDESTROY,#WM_DESTROY
so Alt-F4 will also close the program now...
* GetWindowRect_(WinHandle,@winrect) [...]
put the new button to the left side now, the position seems to be not very accurate...
Michael
Code: Select all
; Define
Global oldproc,quit=0,backbutton,cebutton,clearbutton,one,two,three
Global four,five,six,seven,eight,nine,zero,point
Global winrect.RECT
; EndDefine
Procedure ButtonProc(hwnd,msg,wParam,lParam)
Select msg
Case #WM_NCDESTROY,#WM_DESTROY
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)
SendMessage_(nine, #BM_CLICK,0,0)
SendMessage_(two, #BM_CLICK,0,0)
SendMessage_(six, #BM_CLICK,0,0)
SendMessage_(five, #BM_CLICK,0,0)
EndSelect
ProcedureReturn CallWindowProc_(oldproc,hwnd,msg,wParam,lParam)
EndProcedure
Procedure GetClearButtons(hwnd,param)
CtrlID=GetDlgCtrlID_(hwnd)
Select CtrlID
Case 81
clearbutton=hwnd
Case 82
cebutton=hwnd
Case 83
backbutton=hwnd
EndSelect
ProcedureReturn 1
EndProcedure
Procedure GetNumbers(hwnd,param)
Select GetDlgCtrlID_(hwnd)
Case 124 : zero=hwnd
Case 125 : one=hwnd
Case 126 : two=hwnd
Case 127 : three=hwnd
Case 128 : four=hwnd
Case 129 : five=hwnd
Case 130 : six=hwnd
Case 131 : seven=hwnd
Case 132 : eight=hwnd
Case 133 : nine=hwnd
Case 85 : point=hwnd
EndSelect
ProcedureReturn 1
EndProcedure
Procedure Init()
CalcProgramID=RunProgram("Calc.Exe","","",#PB_Program_Open)
If CalcProgramID
CalcProcessID=ProgramID(CalcProgramID)
Count=0
Repeat
Delay(100) ; Avoid hanging of windows during start of application while searching for the window
Count=Count + 1 ; Security counter to avoid hanging
WinHandle=FindWindow_(0,0)
While WinHandle <> 0
GetWindowThreadProcessId_(WinHandle,@ProcessID)
If ProcessID=CalcProcessID
c=WinHandle
Break
EndIf
WinHandle=GetWindow_(WinHandle,#GW_HWNDNEXT)
Wend
Until c Or (Count=50) ; Wait up to 5 seconds for window to occur
EndIf
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 ; Standard
If OSVersion()=#PB_OS_Windows_NT_4
yPosPIButton=46
Else
yPosPIButton=37
EndIf
GetWindowRect_(WinHandle,@winrect)
x=winrect\left+2;???
y=winrect\top+yPosPIButton+2;???
GetWindowRect_(backbutton,@winrect)
winrect\bottom-winrect\top
winrect\right-winrect\left
winrect\left-x
winrect\top-y
SetWindowPos_(backbutton,0,winrect\left+30,winrect\top,34,winrect\bottom,#SWP_NOZORDER|#SWP_FRAMECHANGED)
button=CreateWindowEx_(0,"Button","PI",#WS_CHILD|#WS_VISIBLE,winrect\left,winrect\top,28,winrect\bottom,c,0,GetModuleHandle_(0),0)
EndIf
RedrawWindow_(button,0,0,#RDW_UPDATENOW)
Else
MessageRequester("OOPS!","Can't find the Calculator!",#MB_ICONERROR)
End
EndIf
oldproc=SetWindowLong_(button,#GWL_WNDPROC,@ButtonProc())
EndProcedure
Init()
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
- Psychophanta
- Always Here
- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
Re: Win API: Add a control to an unowned application
Is there any other way to get the app title (caption) which works in win 7?
Re: Win API: Add a control to an unowned application
Do you mean find the Window Title?
Code: Select all
Structure FindWindowData
hFW.l ; variable to store a handle
sFW.s ; variable to store a Window name
cFW.s ; variable to store a window class name
EndStructure
Global NewList WindowList.FindWindowData()
Procedure.l EnumWindowsCallBack(hFind, lParam)
WindowName.s = Space(255)
WindowClass.s = Space(255)
If GetWindowText_(hFind, WindowName, 255)
Result = GetClassName_(hFind, WindowClass, 255)
AddElement(WindowList())
WindowList()\hFW = hFind
WindowList()\sFW = WindowName
WindowList()\cFW = WindowClass
EndIf
ProcedureReturn #True
EndProcedure
Window$=LCase("Purebasic")
If EnumWindows_(@EnumWindowsCallBack(), 0)
ResetList(WindowList())
While NextElement(WindowList())
Debug("Window: " + WindowList()\sFW)
If FindString(LCase(WindowList()\sFW), Window$, 1)
Found$=(WindowList()\sFW)
Debug "------- Found Our Window ---------"
Debug "hwd : "+WindowList()\hFW
Debug "Caption :"+#DQUOTE$+Found$+#DQUOTE$
Break
EndIf
Wend
EndIf
----
R Tape loading error, 0:1
R Tape loading error, 0:1
- Psychophanta
- Always Here
- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
Re: Win API: Add a control to an unowned application
I open 'cmd.exe' and looks like your tip does not find item_uk wrote:Do you mean find the Window Title?
Code: Select all
Structure FindWindowData hFW.l ; variable to store a handle sFW.s ; variable to store a Window name cFW.s ; variable to store a window class name EndStructure Global NewList WindowList.FindWindowData() Procedure.l EnumWindowsCallBack(hFind, lParam) WindowName.s = Space(255) WindowClass.s = Space(255) If GetWindowText_(hFind, WindowName, 255) Result = GetClassName_(hFind, WindowClass, 255) AddElement(WindowList()) WindowList()\hFW = hFind WindowList()\sFW = WindowName WindowList()\cFW = WindowClass EndIf ProcedureReturn #True EndProcedure Window$=LCase("Purebasic") If EnumWindows_(@EnumWindowsCallBack(), 0) ResetList(WindowList()) While NextElement(WindowList()) Debug("Window: " + WindowList()\sFW) If FindString(LCase(WindowList()\sFW), Window$, 1) Found$=(WindowList()\sFW) Debug "------- Found Our Window ---------" Debug "hwd : "+WindowList()\hFW Debug "Caption :"+#DQUOTE$+Found$+#DQUOTE$ Break EndIf Wend EndIf

Re: Win API: Add a control to an unowned application
change
It found the console on my machine.
Code: Select all
.
.
WindowList()\hFW = hFind
WindowList()\sFW = WindowName
WindowList()\cFW = WindowClass
Debug WindowName
EndIf
.
.
.
Window$=LCase("cmd.exe")
.
.
----
R Tape loading error, 0:1
R Tape loading error, 0:1
- Psychophanta
- Always Here
- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
Re: Win API: Add a control to an unowned application
Thanks a lot, it is useful to me.