Jump to content



Photo

C++, Get hWnd by Class Name and PID, Almost solved but tips are welcomed.


  • Please log in to reply
19 replies to this topic

#1 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 27 February 2012 - 04:02 PM

Look, in AutoIt, i can find the main window of a process this way:
Func _ProcessGetWindow($iProcessID, $sTitle, $sText = '') Local $aWinList = WinList($sTitle, $sText) For $i = 1 To $aWinList[0][0]   If WinGetProcess($aWinList[$i][1]) = $iProcessID Then    Return $aWinList[$i][1]   EndIf Next EndFunc

However i believe a process can have more than one main window ( i mean windows that are not the child window of any other windows ) even with same classname, but hopefully in this case ( what i want to get to work ), it doesn't have more than one window with same classname.

What makes it a little harder to me is that i'm coding a Dll to be injected in a process, i know i can use GetCurrentProcessId() API to retrieve the PID of the process that i had injected my Dll into it.
DWORD PID = GetCurrentProcessId();


Now i want to get the handle of the window with classname "SkinWindow" and this PID.

I have no idea how to do it, however i tried a lot and i found that a combination of EnumWindows(), GetWindowThreadProcessId() is somehow a way to do it, but as i'm new to C++ and EnumWindows() needs structure, callback :-?? etc i always stuck at this.

Any help is welcomed and would be great.

Edited by D4RKON3, 27 February 2012 - 08:47 PM.






#2 Manadar

Manadar

    Taking a REST.

  • MVPs
  • 10,714 posts

Posted 27 February 2012 - 04:20 PM

You can write something yourself easily. I suspect it would look something like this:

#include <Array.au3> Func _ProcessGetWindow($iProcessID, $sTitle, $sText = '')     Local $aRet[1]     Local $aWinList = WinList($sTitle, $sText)     For $i = 1 To $aWinList[0][0]         If WinGetProcess($aWinList[$i][1]) = $iProcessID Then             _ArrayAdd($aRet, $aWinList[$i][1])         EndIf     Next     $aRet[0] = UBound($aRet)     Return $aRet EndFunc


#3 guinness

guinness

    guinness

  • MVPs
  • 10,245 posts

Posted 27 February 2012 - 04:23 PM

There is also a function in WinAPIEx called _WinAPI_EnumProcessWindows.

Example List: _AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_DesktopDimensions()_DisplayPassword()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUISetIcon()_Icon_Clear()/_Icon_Set()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringIsValid()_StringReplaceWholeWord()_StringStripChar()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()AutoIt SearchAutoIt3 PortableAutoItWinGetTitle()/AutoItWinSetTitle()CodingFileInstallrGeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIGetBkColor()LockFile()PasteBinSciTE JumpSignature CreatorWM_COPYDATAMore Examples...Updated: 11/04/2013


#4 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 27 February 2012 - 05:35 PM

I'm so sorry,
Maybe i asked my question in a wrong way,
I'm trying to do it in C++ not AutoIt :|

BTW, thanks for the time you'd spent on my thread.

#5 Mat

Mat

    43 38 48 31 30 4E 34 4F 32

  • MVPs
  • 4,040 posts

Posted 27 February 2012 - 05:36 PM

So you take off the _WinApi_ prefix from Guinness' suggestion. What's the problem?

I don't know where I'm going, but I'm on my way.


#6 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 27 February 2012 - 05:52 PM

Thanks for your attention Mat,

I'm injecting my Dll to a process, i want to change the text of some controls within one of the window of that process from the Dll, sometimes i run multiple instance of that process so FindWindow() can't be a good idea.
The process have a window, with classname SkinWindow, i want to get the Handle of this window, in other hand as i usually have multiple instance of that program running at the same time, my current code fails some times ( Cause i simply used FindWindow() and it sometimes returns the window handle of other instance of the program ), i was thinking about using GetWindowThreadProcessId() to compare the returned PID by with GetCurrentProcessId() to make sure the returned window handle belongs to the current process, but i have no idea about how to do this, actually i have the idea but i can't code it in C++.

I think a combination of,
GetCurrentProcessId()
FindWindow() or maybe FindWindowEx()
GetWindowThreadProcessId()
can do the trick, but i stuck at the step that i need to check the next window when the first window handle returned by FindWindow() doesn't match the current PID.

Please to not ask me to show my current code, cause each time i posted some C++ code i got blamed :-??

#7 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 27 February 2012 - 06:37 PM

Finally i have done it this way, working fine for me:
HWND GetGarenaWindow() { HWND hWnd = FindWindow("SkinWindow", NULL); while (!ComparePIDs(hWnd))   hWnd = FindWindowEx(NULL, hWnd, "SkinWindow", NULL); return hWnd; } bool ComparePIDs(HWND hWnd) { DWORD CurrentPID = GetCurrentProcessId(); DWORD TargetPID = NULL; GetWindowThreadProcessId(hWnd, &TargetPID); if (CurrentPID == TargetPID)   return true; else   return false; }



Any suggestion for improving it?

#8 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 27 February 2012 - 08:01 PM

Stop using a 4 line if...else block to return a boolean result based on the results of a boolean test. All you need is return CurrentPID == TargetPID; which does 4 lines of work in a single line. It's much clearer, cleaner and shorter (without sacrificing readability).

#9 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 27 February 2012 - 08:35 PM

Wow, i can name it the tips of the day.

I remember i used something with " ? true:false " in my other thread but you rejected using that, may i know why? Cause i saw it in some almost professorial source, how ever i stopped using that and used a 4 line if...else instead :|

#10 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 27 February 2012 - 09:46 PM

There's nothing wrong with ternaries if used correctly. I use them quite a bit (much to Jon's chagrin at one time) to initialize variables. They can lead to concise code. However, the code you show above - or the ternary equivalent - do a boolean test to return the result of that boolean test. So skip the extra lines of code. You don't need to test if something is true to return true. Just return the result of the test and you're done.
  • D4RKON3 likes this

#11 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 28 February 2012 - 07:16 PM

Off-topic,
I used this to get the size of a Module:
DWORD GetModuleSize(char *ModuleName) { HMODULE hModule = GetModuleHandle(ModuleName); MODULEINFO ModuleInfo = {0}; GetModuleInformation(GetCurrentProcess(), hModule, &ModuleInfo, sizeof(MODULEINFO)); return ModuleInfo.SizeOfImage; }


Usage:
DWORD Size = GetModuleSize(NULL);

*** Using NULL returns the size of main executable, because of the behavior of GetModuleHandle(),

And i include <Psapi.h> as said here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683201(v=vs.85).aspx

But when i'm going to compile my source, it gives me this error:
error LNK2001: unresolved external symbol _GetModuleInformation@16 fatal error LNK1120: 1 unresolved externals


I have no idea why :|

#12 ProgAndy

ProgAndy

    You need AutoItObject

  • MVPs
  • 2,508 posts

Posted 28 February 2012 - 07:31 PM

You have to link against psapi.lib if you want to use the executable on 2000 and XP. Read the Remarks and Requirements sections :oops:
*GERMAN* Posted Image [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

#13 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 28 February 2012 - 07:45 PM

I'm on Windows 7 Ultimate 32-bit
And if it's matter, i'm coding a Dll to be injected on a process, i'm almost done.

How to link something? I saw Linker settings on my project's setting but i have no idea where and what to link.

#14 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 28 February 2012 - 07:55 PM

You should not be injecting code if you do not have basic understanding of how your linker works.

#15 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 28 February 2012 - 09:05 PM

OK, i'm almost agree with you but, do you know why?
I didn't started C++ from its basics but i was familiar with Computer-Programming when i started playing with C++. I had no time for learning the very basics so i had started coding what was my need exactly, it's why i'm going to be annoying by asking such questions.
I didn't forgot here is AutoIt's forum, but here is the only place i think i can find someone :|

Now, if somebodyjust answer my current question, it's a great help for me.

#16 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 28 February 2012 - 09:11 PM

For fuck's sake use Google. The very first Google result for LNK1120 takes you to MSDN which directs you to LNK2001. You were given both of those errors. USE THEM, THAT'S WHY THEY ARE THERE. Look them up. Learn what they mean and how to fix them. You don't need to ask us. THIS IS DOCUMENTED.
  • shanet likes this

#17 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 28 February 2012 - 09:17 PM

I deleted your last post. Think about some of the content of that post, please.

#18 D4RKON3

D4RKON3

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 372 posts

Posted 29 February 2012 - 07:20 AM

OK, sorry, i didn't realize the forum rules about AutoIt should be followed about C++ too.

#19 Valik

Valik

    Former developer.

  • Active Members
  • PipPipPipPipPipPip
  • 18,879 posts

Posted 29 February 2012 - 04:12 PM

/facepalm
  • shanet likes this

#20 Richard Robertson

Richard Robertson

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 9,692 posts

Posted 01 March 2012 - 03:24 AM

OK, sorry, i didn't realize the forum rules about AutoIt should be followed about C++ too.


  • shanet likes this




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users