Win API: Add a control to an unowned application

Share your advanced PureBasic knowledge/code with the community.
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Post by ricardo »

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.
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

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

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
User avatar
Psychophanta
Always Here
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

Post by Psychophanta »

Is there any other way to get the app title (caption) which works in win 7?
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Win API: Add a control to an unowned application

Post by em_uk »

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
User avatar
Psychophanta
Always Here
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

Post by Psychophanta »

em_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
I open 'cmd.exe' and looks like your tip does not find it :(
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
em_uk
Enthusiast
Enthusiast
Posts: 366
Joined: Sun Aug 08, 2010 3:32 pm
Location: Manchester UK

Re: Win API: Add a control to an unowned application

Post by em_uk »

change

Code: Select all

.
.
WindowList()\hFW = hFind
WindowList()\sFW = WindowName  
WindowList()\cFW = WindowClass
Debug WindowName
EndIf

.
.
.
Window$=LCase("cmd.exe")
.
.
It found the console on my machine.
----

R Tape loading error, 0:1
User avatar
Psychophanta
Always Here
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

Post by Psychophanta »

Thanks a lot, it is useful to me.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Post Reply