Jump to content

GetDlgItem by ClassnameNN


FaridAgl
 Share

Recommended Posts

In AutoIt we have ControlSetText that works with CtrlID or Ctrl Classname, i'm going to do such thing in C++, it works fine with CtrlID but i'm looking for a way to use ClassnameNN ( What AutoIt Info gives me ) rather than CtrlID, take a look at my code please.

Function:

int ControlSetText(char * WindowClass, int CtrlID, char * Text)
{
HWND hWnd = FindWindow(WindowClass, NULL);
if (hWnd == NULL)
return -1;

HWND hCtrl = GetDlgItem(hWnd, CtrlID);
if (hCtrl == NULL)
return -2;

LRESULT Result = SendMessage(hCtrl, WM_SETTEXT, NULL, (LPARAM)Text);
if (Result = false)
return -3;

return 1;
}

Usage:

ControlSetText("Notepad", 15, "Test Text");

As you can see, this function takes CtrlID (15 in here), it's Notepad's main Edit control with ClassnameNN "Edit1", is there any possibility to use "Edit1" instead of 15?

Link to comment
Share on other sites

Looks like C to me. But anyway. You are also using if(Result = false) which looks like you missed an equals sign :)

The number is the instance, the "Edit" bit is the classname. Enumerate through all child windows with the "Edit" class until you reach the Nth one (in this case it's the first one).

In terms of making a C function that does that, you'd probably want to have a function more like:

int ControlSetText( char* WindowClass, char* ControlClass, int ControlInstance, char* text )

Saves you having to go through the messy task of splitting up the string and checking to make sure it's in the right format.

When I said enumerate further up, I didn't mean blindly EnumChildWindows, Something like this instead:

int i;
HWND ret;

ret = NULL;

for ( i = 0; i < ControlInstance; i++ )
{
    ret = FindWindowEx( hParent, ret, ControlClass, NULL );
}

That will find child windows of hParent with class name ControlClass, starting with the control after ret, so each iteration finds the Nth item. I don't know of any way to do that directly.

Edited by Mat
Link to comment
Share on other sites

Looks like C to me. But anyway. You are also using if(Result = false) which looks like you missed an equals sign

Yep, my miss.

Thanks for your great explanations, i get it to work using your method, here it is, tested in several windows and controls and working fine.

bool ControlSetText(char *WindowClass, char *ControlClass, int ControlInstance, char *Text)
{
HWND hwndParent = FindWindow(WindowClass, NULL);
if (hwndParent == NULL)
  return false;

HWND hwndChildAfter = NULL;
for (int i = 0 ; i < ControlInstance ; i++)
  hwndChildAfter = FindWindowEx(hwndParent, hwndChildAfter, ControlClass, NULL);
LRESULT Result = SendMessage(hwndChildAfter, WM_SETTEXT, NULL, (LPARAM)Text);
if (Result == NULL)
  return false;
return true;
}

Now that i can find any control handle withing any window using Classname and Instance, i'm pretty sure i can easily code most of AutoIt's control related functions in C++.

Thanks Mat.

Link to comment
Share on other sites

Some simple funcs:

WinGetHandle

WinActive

WinExists

WinGetProcess

HWND WinGetHandle(char *WindowClass)
{
return FindWindow((LPCTSTR)WindowClass, NULL);
}
bool WinActive(HWND WindowHandle)
{
return GetForegroundWindow() == WindowHandle ? true:false;
}
bool WinExists(char *WindowClass)
{
return FindWindow((LPCTSTR)WindowClass, NULL) != NULL ? true:false;
}
DWORD WinGetProcess(HWND WindowHandle)
{
DWORD PID = NULL;
GetWindowThreadProcessId(WindowHandle, &PID);
if (PID != NULL)
  return PID;
else
  return NULL;
}
Link to comment
Share on other sites

Well that code's a horror show. You're missing some basics. Rule #138: If you find that you have to use a cast a lot then you're using the wrong type somewhere to begin with. You also failed to even think about some of the code. You test PID for non-NULL and then return it's value, or you return NULL. What did that code accomplish?

Link to comment
Share on other sites

Well that code's a horror show. You're missing some basics. Rule #138: If you find that you have to use a cast a lot then you're using the wrong type somewhere to begin with. You also failed to even think about some of the code. You test PID for non-NULL and then return it's value, or you return NULL. What did that code accomplish?

Well, actually you are right about the PID, thanks for that. I usually make some mistakes in my codes and i need to reread them later with more focus to fix them out.

I'm almost a beginner in C++, but i like it and i'm trying to learn more. These codes aren't a challenge for me, just some kind practices for further uses.

An important thing about me, i never forget what i learned.

I made these function so far, at least working for me.

WinGetHandle

WinActive

WinExists

WinGetProcess

WinSetState

WinMove

However i believe what AutoIt presents in similar functions are extremely better, but at the moment i'm in a situation that i MUST write some of these functions in C++.

HWND WinGetHandle(char *WindowClass)
{
return FindWindow((LPCTSTR)WindowClass, NULL);
}
bool WinActive(char *WindowClass)
{
HWND hWnd = WinGetHandle(WindowClass);

if (GetForegroundWindow() == hWnd)
  return true;
else
  return false;
}
bool WinExists(char *WindowClass)
{
HWND hWnd = FindWindow((LPCTSTR)WindowClass, NULL);
if (hWnd != NULL)
  return true;
else
  return false;
}
DWORD WinGetProcess(char *WindowClass)
{
HWND hWnd = WinGetHandle(WindowClass);

DWORD PID = NULL;
GetWindowThreadProcessId(hWnd, &PID);
return PID;
}
bool WinSetState(char *WindowClass, int State)
{
HWND hWnd = WinGetHandle(WindowClass);
if (ShowWindow(hWnd, State) != 0)
  return true;
else
  return false;
}
bool WinMove(char *WindowClass, int X, int Y)
{
HWND hWnd = WinGetHandle(WindowClass);
if (SetWindowPos(hWnd, HWND_TOP, X, Y, 0, 0, SWP_NOSIZE) != 0)
  return true;
else
  return false;
}
Edited by D4RKON3
Link to comment
Share on other sites

Mat, that's also superfluous. The same is accomplished by return Result != NULL.

That's why I posted it.

As a C programmer, the only thing you are using in your code that is C++ is the bool type. If you replaced that with the winapi BOOL type and used TRUE and FALSE instead of true and false then you'd be writing C, not C++. On the other hand, if you are writing C++, you should probably be exposing functions that take string arguments (then using c_str() before passing it to the functions), rather than char*. Not that I have any expertise whatsoever with C++.

Link to comment
Share on other sites

These codes aren't a challenge for me, just some kind practices for further uses.

So that's why almost every single thing about the code is wrong?

Assuming you are writing C then you're using a C++ type (bool) so that's wrong.

Assuming you are using C++ then you are using C-style casts which is wrong. See this bug? The root cause of that is a C-style cast done by somebody who doesn't understand what their code does. What's cast away is const. This allows a const string which has it's lifetime managed elsewhere to be returned from a function it shouldn't be returned from. This string is later deleted incorrectly which leads to undefined behavior when it's deleted for a second time. Production releases of AutoIt act weird, running it under the debugger generates an assertion. All because somebody thought lazy C-style casts were a good idea.

No matter what language the casts are just plain wrong to begin with. LPCTSTR is defined as const wchar_t * if the UNICODE flag is set. That is not the same thing as the char *you are passing. Either do not cast at all (if you only need to use the ANSI version) or your functions need to take LPCTSTR parameters if you do care about ANSI/UNICODE compatibility.

In addition your input parameters are not declared as const. Believe it or not const-correctness is important and should be learned early only.

We've already discussed the other problems in the code concerning return values.

Link to comment
Share on other sites

Thanks to both of you, i never said i know everything about C &amp; C++ or i'm an expert, as i said i'm new to C &amp; C++ and i'm just trying to learn.

Your comments are great for me Valik.

Mat. thanks for c_str(), now i will use an string object instead of char *.

Thanks guys.

Edited by D4RKON3
Link to comment
Share on other sites

After all of these, i finally found something :|

AutoItX3.dll and AutoIt3.h

I can include AutoIt3.h in my C++ source, but what else should i do to become able to use AutoIt functions?

I need a little help to get it to work.

An other question, when i compiled my source and want to use it some where else, i mean on a windows without AutoIt installed, do i need to copy the AutoItX3.dll ?

If it helps, i should say i'm coding a Dll to inject it, AutoItX3.dll will work in this case as well as exe projects?

Link to comment
Share on other sites

OK, so far i had included AutoItX.h in my project, then i tried these codes:

AU3_BlockInput(1);
AU3_Sleep(5000);
AU3_BlockInput(0);

But it gives me these errors:

error LNK2001: unresolved external symbol _AU3_Sleep@4
error LNK2001: unresolved external symbol _AU3_BlockInput@4
fatal error LNK1120: 2 unresolved externals
Link to comment
Share on other sites

You don't know what to search for? You have an error ID there. You have an error string there. I'm pretty fucking sure you have everything you need to look up your problem online. If you can't... then you aren't ready for C++.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...