C++ Winapi HWND Get element by Name - c++

Is there a way I can get a HWND by it's property "name"? I know that every IDE has its own properties for HWND elements but those properties are applied to the HWND.
I'm not working in Visual Studio, this is just a case. I want to get HWNDs by Name in C++ without VS Libraries.
For example:
HWND button = GetHwndByName("button1"); //Example
Property "name" is button1

I'm going to assume you're either trying to access your GUI controls in code or some other program's GUI controls.
As some people have mentioned, the (name) property in the properties editor is just the variable name used for that control. Your screenshot shows Visual Studio editing a .net program. In the case of .net, the (name) field is the name of the class member of the window class that represents the control. So if (name) is button1 then Visual Studio might generate code like
// pseudo-C++/C#-like
class Form1 : public System.Windows.Forms.Form {
private:
System.Windows.Forms.Button *button1;
...
};
The idea here is that you would have event handlers as part of your Form1 class:
void Form1::onButton1Clicked(void)
{
this->button1->SetText("You clicked me!");
}
As such, the (name) is not an intrinsic property of the window from Windows's point of view.
I don't know what CA Plex's GUI editor looks like, but I would assume, given you said you were using C++, that it either
a) produces a class like the one I pasted above, in which case you would just use the (name) directly as members, or
b) produces a header file with each of those control names as global HWND variables
Either way, you can just use them directly from within your code. Perhaps have something like
void doToAllButtons(void (*f)(HWND, LPARAM), LPARAM lParam)
{
(*f)(button1, lParam);
(*f)(button2, lParam);
(*f)(button3, lParam);
}
and simply write an appropriate function to call via this one.
If you need to interface with another program and want to use its variable names, then you're out of luck. You'll need to find the windows you want some other way, such as with FindWindow().

Related

How to get Edge window handle (HWND)?

I created edge browser window using CreateCoreWebView2Host() method. This method is takes parent window handle and creates child window in which we can navigate the web page. After I am done with navigation I need to return my window handle, which I believe I am failed to return.
On Spy++ I see "Chrome_WidgetWin_0", "Chrome_WidgetWin_1", "Intermediate D3D Window" as child windows to my parent window. which one is the child window handle?I thought I am creating one child window.
I tried by fetching window handles using FindWindowEx() passing above mentioned class names. But still not getting expected results in my project. So I doubt if I am passing correct handle.
Now the question is , How to get the window handle(HWND) for the window created by CreateCoreWebView2Host?
You can get the edge window handle by using GetWindow, passing Handle of WebView2 control to it as the first argument and GW_CHILD as second argument. For exaample:
public const uint GW_CHILD = 5;
[DllImport("user32.dll")]
public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
[DllImport("user32.dll")]
public static extern IntPtr SetFocus(IntPtr hWnd);
WebView2 webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
private async void Form1_Load(object sender, EventArgs e)
{
webView21.Dock = DockStyle.Fill;
this.Controls.Add(webView21);
await webView21.EnsureCoreWebView2Async();
webView21.Source = new Uri("https://bing.com");
webView21.NavigationCompleted += WebView21_NavigationCompleted;
}
private void WebView21_NavigationCompleted(
object sender, CoreWebView2NavigationCompletedEventArgs e)
{
var child = GetWindow(webView21.Handle, GW_CHILD);
SetFocus(child);
}
Note: You may find this GitHub thread useful. This is the trick that I've used to focus the browser in Windows Forms as well.
The WebView2 SDK doesn't provide this HWND because exactly how the WebView2 connects up to the provided parent HWND is intended to be an implementation detail that could change as the underlying Edge browser or WebView2 Runtime is updated even when you stay on the same version of the WebView2 SDK. We're relying in large part on the browser's logic for rendering and so this may change in the future.
Instead of providing an HWND, the CoreWebView2Host (its been renamed to CoreWebView2Controller in more recent SDK releases) provides various methods for you to focus, zoom, and so on. What are you trying to do with the HWND?

CWindowImpl - Create() returns error code 1406

I just tried to setup a small win32 project, and was just about to create a window.
I created a dialog in the resource designer and set up this class for my window:
#pragma once
#include "stdafx.h"
class TTTMainDialog : public CWindowImpl<TTTMainDialog>
{
public:
DECLARE_WND_CLASS(_T("TTTDlg"))
enum { IDD = IDD_TTT_DIALOG };
BEGIN_MSG_MAP_EX(MusicPlayerDialog)
MSG_WM_INITDIALOG(OnInitDialog);
MSG_WM_CLOSE(OnClose);
MSG_WM_DESTROY(OnDestroy);
END_MSG_MAP()
TTTMainDialog();
~TTTMainDialog();
private:
const BOOL OnInitDialog(const CWindow wndFocus, const LPARAM lInitParam);
void OnClose();
void OnDestroy();
};
As you can see, I added the window class declaration, I inherited CWindowImpl, I registered the dialog. I don't think I forgot something here.
In the class which is supposed to create the dialog, I tried to create it like this:
TTTMainDialog myDialog;
HWND handle = myDialog.Create(NULL);
myDialog.ShowWindow(nCmdShow);
However, the Create method does return NULL all the time. I checked the error code with GetLastError(), and it turns out i am getting error code 1406, or "ERROR_TLW_WITH_WSCHILD".
The msdn documentation says the following about this error:
"Cannot create a top-level child window."
I tried to google up on this, but there is not much to find.
If I had to take a guess I would say the problem is caused by some window class name details, but i'm really not sure.
Any advice?
You are trying to build a window class from wrong pieces.
The error is pretty descriptive: you are trying to create a parentless window with a WS_CHILD style and this does not work out.
You get the child style from default template parameter: CWindowImpl -> CWindowImplBaseT -> TWinTraits -> CControlWinTraits. CControlWinTraits is supposed for use with child control windows.
If you are going to use a dialog template (IDD_TTT_DIALOG) then the proper base class is CDialogImpl, which is already prepared to use proper window styles. Also, it has what it takes to create both modal and modeless dialogs. The latter act more like windows and are non-blocking but in the same time take dialog template resource with predefined controls.
Small example for CDialogImpl use
Or, another one

How to access Mainfrm member variable status without using ((CMainFrame*) AfxGetMainWnd ())->...?

I have a MDI appliation in MFC to modify. I want to check the value of a flag which is a member variable of MainFrm from a lower level class. But I don't want to access it using
'((CMainFrame*) AfxGetMainWnd ())->IsFlagOn()' kind of function because for that i have to give the mainfrm.h in a lower level class. I somehow feel this will create some circular reference later, after reading this Why are circular references considered harmful?
what are the other ways to get the flag value from mainfrm class.Please guide !
note: here class hierarchy is mainfrm->CTestExplorerFrame->CTestExplorerView->CTestExplorerTreeCtrl
I want to check from the lowest level about a flag that is only accessed by mainfrm
AfxGetMainWnd() returns a CWnd* that you can use to communicate with the mainframe via the Windows message system. Define a custom message and send this message to the CWnd*
#define UWM_MYREQUEST (WM_APP + 2)
int datatoget;
CWnd* pMainframe = AfxGetMainWnd();
pMainframe->SendMessage(UWM_MYREQUEST, (WPARAM)&datatoget, 0);
The mainframe needs code like this to receive and handle the custom message:
ON_MESSAGE(UWM_MYREQUEST, OnMyRequest)
LRESULT CMainFrame::OnMyRequest(WPARAM wparam, LPARAM lparam)
{
int* ptoget = (int*)wparam;
*ptoget = m_datarequested;
return 0;
}
I would declare an (pure virtual) interface class where you have a pure virtual call to get the value of the flag you are interested in at CTestExplorerTreeCtrl. Then the MainFrame implements this interface class and passes a pointer to CTestExplorerTreeCtrl. This way you can avoid any references to the MainFrame class.

Wrapping a PropertySheet; how to handle callbacks?

I'm writing an (unmanaged) C++ class to wrap the Windows PropertySheet. Essentially, something like this:
class PropSheet {
PROPSHEETHEADER d_header;
public:
PropSheet(/* parameters */);
INT_PTR show();
private:
static int CALLBACK *propSheetProc(HWND hwnd, UINT msg, LPARAM lParam);
};
The constructor just initializes the d_header member:
PropSheet::PropSheet(/* parameters */) {
d_header.dwSize = sizeof(PROPSHEETHEADER);
d_header.dwFlags = PSH_USECALLBACK;
// ...
d_header.pfnCallback = &propSheetProc;
// ...
}
After which I can show it, modally, with:
INT_PTR PropSheet::show() {
return PropertySheet(&d_header);
}
Now the problem is, because the callback is static, that it cannot access the wrapper class. If this were a normal window, with a WindowProc instead of a PropSheetProc, I could attach some extra data to the window using cbWndExtra in WNDCLASS, in which I could store a pointer back to the wrapper, like in this article. But property sheets do not offer this functionality.
Furthermore, because the property sheet is shown modally, I can execute no code between the creation and destruction of the actual window, except when that code is executed through the callback or one of the sheets's window procedures.
The best solution I've come up with so far is to, right before showing the property sheet, store a pointer to the wrapper class inside a global variable. But this assumes that I'll only be showing one property sheet at a time, and is quite ugly anyway.
Does anyone have a better idea how to work around this?
As you are showing the property sheet modally, you should be able to use the parent window (i.e. its handle) of the property sheet to map to an instance, using ::GetParent() on the hwndDlg parameter of PropSheetProc().
Awesome, yet another Win32 API that uses callbacks without a user-defined context parameter. It is not the only one, alas. e.g. CreateWindow is bad (it gives you user-defined context, but that context isn't available for the first few window messages), SetWindowsHookEx is even worse (no context at all).
The only "solution" that is general-purpose and effective is to emit a small piece of executable code with a 'this' pointer hardcoded. Something like this: http://episteme.arstechnica.com/eve/forums/a/tpc/f/6330927813/m/848000817831?r=848000817831#848000817831
It's horrible.
The PROPSHEETPAGE structure has an lParam field available for callbacks. In your PROPSHEETHEADER, you can include the PSH_PROPSHEETPAGE flag to pass an array of PROPSHEETPAGE items describing your pages, or omit the flag to pass an array of preallocated HPROPSHEETPAGE handles instead (which means using CreatePropertySheetPage(), and thus using PROPSHEETPAGE anyway).
You've already admitted "I can execute no code between the creation and destruction of the actual window". It seems that a global variable wouldn't be a terrible hack.
I've found another option: using SetProp to add a property that stores the pointer to the wrapper. Only requires the global variable once, to be able call SetProp from the property sheet callback.

How to keep global variable value unchanged in ATL project?

I need help on global variable usage in an ActiveX(ATL) project. Basically the ActiveX component function is to navigae to a specified URL in composite control(webbrowser embedded). The URL string is initialize in the beginning and saved in a global variable. here is my source code file of ActiveX project.
(Do not be concerned about the grammar, I just want to show the code flow).
MyComponentInit.cpp
// MyComponentInit.cpp : Implementation of MyComponentInit.cpp
#include "stdafx.h"
#include <ios>
char szURL[1024] = "\0"; // global variable holding URL string
STDMETHODIMP CMyComponentInit::InitPlugin(BSTR url)
{
// convert BSTR to string
......
memcpy(szURL, szUrl, len);
}
MyComponentCtrl.cpp
// MyComponentCtrl.cpp : Implementation of MyComponentCtrl.cpp
#include "stdafx.h"
extern char szURL[1024]
LRESULT CMyComponentCtrl::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
......
m_spWebbrowser->Navigate(szURL, &v, &v, &v, &v);
}
The use of mycomponent ActiveX is in a MFC SDI(Single Doc/View) test application. The flow is like:
In App Initinstance, I called activeX InitPlugin to initialize the URL string.
In a Information dialog window, insert MyComponentCtrl ActiveX, the Information dialog is brought up by clicking Mainframe Information menu item. The goal is when Information dialog window pop up, it can always go to the specified url.
After my MFC test app starts, I click Information dialog menu, the Information dialog window can be up and navigate to the url correctly.
But the problem is if I close the Information dialog, wait fro a while (around 2~3 minutes), I tried to bring up Information dialog again, it could not navigate to the URL. I debug it and found the global variable szURL in MyComponenet project lost its value.
Can you please tell me what should I do to resolve this problem?
Thanks a lot in advance!
Bionicoder
It looks like the application and COM might be releasing and reloading your DLL between the initialization call and the control being displayed. This could happen if the main app has no active instances of any of the DLL's COM components and subsequently calls CoFreeUnusedLibraries().
You can test that by putting a breakpoint or trace from DllMain for fdwReason == DLL_PROCESS_DETACH. If this is the problem, the breakpoint will trigger after the initialization call but before OnInitDialog().
If this is the problem, you can solve it by initializing the control instance with the URL directly, using instance state instead of using a global variable.
You can alternately keep a reference to the initialization interface for the lifetime of the application.