Is it possible to create a win32 messaging window that won't be found by enumerating? - c++

I'm trying to enumerate all win32 windows using following code:
EnumChildWindows(GetDesktopWindow(),
WindowManager::enumChildWindows,
reinterpret_cast<LPARAM>(this));
BOOL CALLBACK WindowManager::enumChildWindows(HWND hwnd, LPARAM lParam) {
WindowManager* manager = reinterpret_cast<WindowManager*>(lParam);
//
// Do stuff with child window handle (hwnd)
//
// Return TRUE to continue enumeration, FALSE to stop.
return TRUE;
}
So basically, I get the top most window by calling GetDesktopWindow( VOID ) function from WinAPI and enumerate child windows by calling EnumChildWindows( __in_opt HWND hWndParent, __in WNDENUMPROC lpEnumFunc, __in LPARAM lParam) function again from WinAPI.
Simply, my question is, can I be missing any win32 window by this approach? Could anyone hide a win32 window such that this approach can't enumerate it?
Thanks in advance.

For your way (via EnumChildWindows(GetDesktopWindow)) - it is possible: just create message-only window.
P.S. But you can enumerate message-only windows via EnumChildWindows(GetAncestor(FindWindowEx(HWND_MESSAGE,0,0,0),GA_PARENT)): see How come FindWindow finds a window that EnumChildWindows doesn't?.

Related

Is there a solution for this case?

This is a Windows Desktop Application project created by Visual Studio.
I have a Dialog resource created from the Resource View that has a Static Text.
I'm using this dialog in order to show errors to the user:
DialogBox(hInst, MAKEINTRESOURCE(IDD_MY_MESSAGE_BOX), hWnd, MyMessageBoxProc);
The reason I'm using a DialogBox is that I need it to stop the code execution, because the next line of code will close the application I mean the user should be aware of the error message before application exits. I know a way to change the Static Text:
HWND myMessageBox = CreateDialog(hInst, MAKEINTRESOURCE(IDD_MY_MESSAGE_BOX), nullptr, MyMessageBoxProc);
HWND staticText = GetDlgItem(myMessageBox, IDC_STATIC);
SetWindowText(staticText, L"Text changed.");
But that approach doesn't stop code execution.
Since it's a Windows Desktop Application project I cannot create MFC classes and try the following approach:
// Find the Static Text.
// If called from within MyMessageBox class.
CWnd *staticText = GetDlgItem(IDC_STATIC);
staticText->SetWindowText("Text changed.");
// If called from elsewhere.
MyMessageBox myMessageBox;
CWnd *staticText = myMessageBox.GetDlgItem(IDC_STATIC);
staticText->SetWindowText("Text changed.");
So what would be a workaround in order to change the Static Text using a DialogBox without the need of MFC classes or even another approach that allows me to change the Static Text and still stop code execution like a DialogBox.
Just change the text in your window procedure (MyMessageBoxProc) by handling WM_INITDIALOG message. If you wish to supply the text to the dialog, then create it using DialogBoxParam instead, which is then accessible via the lParam parameter.
e.g.
INT_PTR MyMessageBoxProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_INITDIALOG) {
HWND hCtrl = GetDlgItem(hWnd, IDC_STATIC);
SetWindowText(hCtrl, reinterpret_cast<LPCTSTR>(lParam));
}
return FALSE;
}
The creation would be something like:
LPCTSTR text = _T("Text changed.");
DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_MY_MESSAGE_BOX), hWnd, MyMessageBoxProc,
reinterpret_cast<LPARAM>(text));
Note that there is a standard message box that ships with windows, which you may want to use instead of writing your own. That's available via the function MessageBox

Win api MessageBox alternative that has a set for text-align: center

As I found out by searching, it is not possible to create a MessageBox() with center-aligned text.
So is there some simple alternative providing the MessageBox() functionality (including program wait for closing/accepting the box) that has an option to center-align the text?
Thanks for suggestions/examples.
PS: On Windows7+, using C++ Windows API (compiled in MS Visual Studio 2012)
EDIT:
Some useful tips:
1) Express version of Visual Studio does NOT have a resource editor/file create option:
You do have a Visual Studio "higher" than express - How to: Add a
Resource File
You have just Express version :
How to
add a resource editor for Express version
Free editor
ResEdit
This MSDN forum page contains some other useful tips like:
From the 'solution explorer', right-click the *.rc file and select
'open with..', then select 'source code (text) editor' from the list.
You might want to 'set as default' to save you repeating those
intitial steps. Once done, you should be able to manually edit the
resource script within Express.
Free XN Resource Editor
2) Visual Studio C++ how to display a dynamic message (i.e., string) in my About box?
As I found out by searching, it is not possible to create a MessageBox() with center-aligned text.
It is not possible to create a center-aligned MessageBox() dialog, as the API does not expose an option for that. But it is possible to manipulate the standard MessageBox()` dialog with some slight trickery to force it to be center-aligned.
Use SetWindowsHookEx() to create a WH_CBT hook for the thread that is calling MessageBox() (no DLL needed). The hook callback allows you to discover the HWND of the dialog that MessageBox() creates. With that, you can manipulate it however you want. In this case, you can use FindWindowEx() to get the HWND of the STATIC control for the dialog's text and then apply the SS_CENTER style to it using SetWindowLong(). For example:
LRESULT CALLBACK CenterMsgBoxTextProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_ACTIVATE)
{
HWND hDlg = (HWND) wParam;
HWND hTxt = FindWindowEx(hDlg, NULL, TEXT("STATIC"), NULL);
if (hTxt)
SetWindowLong(hTxt, GWL_STYLE, GetWindowLong(hTxt, GWL_STYLE) | SS_CENTER);
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
HHOOK hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC) &CenterMsgBoxTextProc, NULL, GetCurrentThreadId());
MessageBox(...);
if (hHook) UnhookWindowsHookEx(hHook);
Alternatively, you can use SetWinEventHook() instead of SetWindowsHookEx():
void CALLBACK CenterMsgBoxTextProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
HWND hTxt = FindWindowEx(hwnd, NULL, TEXT("STATIC"), NULL);
if (hTxt)
SetWindowLong(hTxt, GWL_STYLE, GetWindowLong(hTxt, GWL_STYLE) | SS_CENTER);
}
HWINEVENTHOOK hHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, &CenterMsgBoxTextProc, GetCurrentProcessId(), GetCurrentThreadId(), 0);
MessageBox(NULL, TEXT("test"), TEXT("test"), MB_OK);
if (hHook) UnhookWinEvent(hHook);
Here is what the result looks like in both cases:
Afaik there is not. But it is actually quite easy to create such a dialog using Win32 resources and the DialogBox function.

How to get HWND in ATL DLL (for SendMessage or PostMessage)

I want to get HWND in ATL DLL for SendMessage or PostMessage function in Thread.
but, ATL DLL doesn't have a window.
How to get HWND in ATL DLL?
Project Application Setting : DLL(Dynamic-link library), Security Development Lifecycle, ('not' Support MFC)
Class Option : Apartment, Aggregation Yes, Dual InterFace, Connection points.
HelloCtrl.cpp (VB Client is Handling ShowMessage())
STDMETHODIMP CHelloCtrl::ShowMessage(BSTR bstrCaption, VARIANT_BOOL* lpvbResult)
{
DWORD dwThreadID;
m_hThread_ReadData = CreateThread(NULL, 0, T_ReadData, (LPVOID)this, 0, &dwThreadID);
return S_OK;
}
DWORD WINAPI CHelloCtrl::T_ReadData(LPVOID pParam)
{
CHelloCtrl* hCtrl = (CHelloCtrl*) pParam;
::PostMessage(hCtrl->m_hWnd, WM_KEYDOWN, (WPARAM)NULL, (LPARAM)NULL);
return S_OK;
}
void CHelloCtrl::LeftButton()
{
Fire_OnMouseClick(123, 123);
}
HelloCtrl.h
#define WM_THREADFIREEVENT (WM_USER+1)
BEGIN_MSG_MAP(CHelloCtrl)
CHAIN_MSG_MAP(CComControl<CHelloCtrl>)
DEFAULT_REFLECTION_HANDLER()
MESSAGE_HANDLER(WM_THREADFIREEVENT, OnLeftButtonDown)
END_MSG_MAP()
public:
STDMETHOD(ShowMessage)(BSTR bstrCaption, VARIANT_BOOL* lpvbResult);
LRESULT OnLeftButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
void LeftButton();
private:
HANDLE m_hThread_ReadData;
static DWORD WINAPI T_ReadData(LPVOID pParam);
Window is an object that a process or module might have or might not have, or it might create one if needed. That is, your question does not have an answer without specifying what kind of window and its HWND handle you are looking for. DLL and HWND are unrelated.
From the context, it looks like you want a window which you can use for messaging and to transfer execution control between threads. That is, you post somewhere then handle elsewhere leaving the threading magic to window API.
In this case you can either reuse one of existing windows, such as window created for an ActiveX control, our you simply create your own window you fully control and use for your purposes. For the latter you derive from CWindowImpl and... see Implementing a Window with CWindowImpl. The former might be simpler might be not: ActiveX controls don't have to have a window in which case they are windowless controls. In the same time, you have an option to force windowed control using m_bWindowOnly, see How do I get the HWND for an ActiveX control after the control has been initialised/activated?.

Get Window Handle (HWND) of a window created by a library call

EDIT: I forgot to mention, I do not have source code for the DLL that creates window, so I can't actually change the function to return HWND.
I am creating a Win32 application, and am using a DLL that creates a window for me through one of its exported function "void X();" I call X() in my WinMain().
It does create a window for me. I want to get the HWND of the window that was created by this exported library function, as X() returns void, so I can use it for other API calls.
Can someone tell the easiest to get the HWND?
I have searched and questions answered here, but I cant somehow figure out the exact, appropriate solution. I tried EnumWIndows() and then getting the Process ID, and then comparing with the current thread process ID. But I guess there should be a far better much more efficient and a easy way to get HWND.
After all, I am in the WinMain of the process that created this window in the first place.
If I need to explain anything, that I have missed out writing here, please let me know.
I am sure that this is very basic and am missing something blatantly here. Sorry.
Thanks & Regards!
Use a tool like Spy++ or Winspector to see all of the HWNDs created by your app, in particular their class names and window titles. Then you can copy those values into your code and make a single call to FindWindow() after the DLL has created its window, eg:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ...
X();
HWND hWnd = FindWindow("ClassNameHere", "TitleHere");
// ...
return 0;
}
The easiest way to do that is to use the function SetWindowsHookEx(WH_CBT, fun, NULL, GetCurrentThreadId()). Then the fun function, a callback defined by you, will be called when a number of events happen. The one you want is the HCBT_CREATEWND.
Somethink like that (totally untested):
HWND hDllHandle = NULL;
LRESULT CALLBACK X_CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode == HCBT_CREATEWND)
hDllHandle = (HWND)wParam;
return CallNextHookEx(NULL, nCode, wParam, lParam); //The first parameter is useless
}
HWND CallXAndGetHWND()
{
HHOOK hDllHook = SetWindowsHookEx(WH_CBT, X_CBTProc, NULL, GetCurrentThreadId());
X();
UnhookWindowsHookEx(hDllHook);
//hDllHandle is a global variable, so will be now you window!
return hDllHandle;
}
Note that this function is not thread-aware, but most likely you will call it just once at the beginning of your code, so it shouldn't matter.
And beware! Many functions, even Win32 API functions, create hidden windows. This code will hook all of them and return the last one to be created. Changing it to return any other, or even a list of them, if needed, should be trivial.

C++: How to center MessageBox?

Using Visual Studio C++ with MFC. How do I center a MessageBox to it's parent window? Currently it centers to the desktop.
You need to install a hook and change the dialog box position on creation.
int MessageBoxCentered(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)
{
// Center message box at its parent window
static HHOOK hHookCBT{};
hHookCBT = SetWindowsHookEx(WH_CBT,
[](int nCode, WPARAM wParam, LPARAM lParam) -> LRESULT
{
if (nCode == HCBT_CREATEWND)
{
if (((LPCBT_CREATEWND)lParam)->lpcs->lpszClass == (LPWSTR)(ATOM)32770) // #32770 = dialog box class
{
RECT rcParent{};
GetWindowRect(((LPCBT_CREATEWND)lParam)->lpcs->hwndParent, &rcParent);
((LPCBT_CREATEWND)lParam)->lpcs->x = rcParent.left + ((rcParent.right - rcParent.left) - ((LPCBT_CREATEWND)lParam)->lpcs->cx) / 2;
((LPCBT_CREATEWND)lParam)->lpcs->y = rcParent.top + ((rcParent.bottom - rcParent.top) - ((LPCBT_CREATEWND)lParam)->lpcs->cy) / 2;
}
}
return CallNextHookEx(hHookCBT, nCode, wParam, lParam);
},
0, GetCurrentThreadId());
int iRet{ MessageBox(hWnd, lpText, lpCaption, uType) };
UnhookWindowsHookEx(hHookCBT);
return iRet;
}
::AfxMessageBox() appears on the center of the MainFrame for me. Which is basically a call to ::MessageBox() with a handle to the MainFrame as the first parameter. Isn't that working for you?
You can't. That's why a lot of people write their own MessageBox classes.
Who said "can't"?
Try this:
This is for Win32 API, written in C. Translate it as you need...
case WM_NOTIFY:{
HWND X=FindWindow("#32770",NULL);
if(GetParent(X)==H_frame){int Px,Py,Sx,Sy; RECT R1,R2;
GetWindowRect(hwnd,&R1); GetWindowRect(X,&R2);
Sx=R2.right-R2.left,Px=R1.left+(R1.right-R1.left)/2-Sx/2;
Sy=R2.bottom-R2.top,Py=R1.top+(R1.bottom-R1.top)/2-Sy/2;
MoveWindow(X,Px,Py,Sx,Sy,1);
}
} break;
Add that to the WndProc code... You can set position as you like, in this case it just centres over the main program window. It will do this for any messagebox, or file open/save dialog, and likely some other native controls. I'm not sure, but I think you may need to include COMMCTRL or COMMDLG to use this, at least, you will if you want open/save dialogs.
I experimented with looking at the notify codes and hwndFrom of NMHDR, then decided it was just as effective, and far easier, not to. If you really want to be very specific, tell FindWindow to look for a unique caption (title) you give to the window you want it to find.
This fires before the messagebox is drawn onscreen, so if you set a global flag to indicate when action is done by your code, and look for a unique caption, you be sure that actions you take will only occur once (there will likely be multiple notifiers). I haven't explored this in detail, but I managed get CreateWindow to put an edit box on a messagebox dialog. It looked as out of place as a rat's ear grafted onto the spine of a cloned pig, but it works. Doing things this way may be far easier than having to roll your own.
Crow.
EDIT: Small correction to handle the problem raised by Raymond Chen. Make sure that parent handles agree throughout, and this should work ok. It does for me, even with two instances of the same program...