MFC - random name and class-name of main window / process - c++

Is there any way to change name of process?
I am developing App in MFC c++, but I want it to be invisible for HWND FindWindow(Name Window, Clasename of Window) function.
It is easy to change Caption of main window, but I have no idea how to change classname of Window.

To set the window class name of your main window in MFC you first call AfxRegisterClass (doing this in InitInstance, before the window is created) with your desired classname and then in the mainframe class override CMainFrame::PreCreateWindow and modify the passed in CREATESTRUCT with your desired classname.
This can be useful if you want another process to easily find your main HWND, but it is not very useful to try and make your window invisible to FindWindow.

Related

get handle of window

I have a window which runs in separate thread. I need to get the handle of that window in another thread.
I can't use ::FindWindow API, because the window name will change, as my application can run in other languages. Plus, I don't have access to the resource string used for window name.
I can't use ::GetActiveWindow also, as the calling thread id and the active window thread id is different.
Please suggest some solution.
It is not necessary to pass the window name to the FindWindow function. You can pass NULL for the window name and find the window using only the lpClassName parameter.
MFC normally assigns window class names automatically, but you can control a window's class name by registering a unique name with AfxRegisterClass and creating the window with that registered class name.

Can't return focus to the main window after showing dialog

I create dialog window in MFC using CWnd::DoModal function.
The window is instantiated in CWinApp::OnIdle()
CPatientFile pf;
pf.DoModal();
When the DoModal function returns the focus is not returned to the main window.
I tried to set focus manually
AfxGetMainWnd()->SetFocus();
Also tried to set the main window as foreground or active.
Generally I have touch screen, so when I close the Dialog I need to press the button on the main window to get it work.
So what is the right way to do it?
Just check the constructor of CPatientFile. It may be accepting the parent window CWnd *. Pass the main window as the parent.
Like
CPatientFile pf(this); //if this code is in main window class itelf
or
CPatientFile pf(AfxGetMainWnd());
Updated:
If you have instantiated the dialog from the main window, then the focus will automatically go back to the window when the dialog is closed. I am suspecting that you have instantiated the dialog from the app class itself (CWinApp) after creating the main window. If this is the case then the main window may not get the focus & you must create the dialog from within the main window. Or if you are creating the dialog in a separate thread.
As a work around you can use AfxGetMainWnd()->SetForegroundWindow() or AfxGetMainWnd()->SetActiveWindow(). But first I would try to find the cause of the issue & try to write better code (like suggested in above paragraph).
If you have copy-pasted, the statement is itself incorrect:
CPatientFile pf();
The next line shouldn't compile at all. Why? Because it is declaring a function named pf which returns CPatientFile.
If that is correct, may I ask if there is any multithreading involved. Is another thread creating a window?
How do you check if parent windows has (not) got the focus?

How can I register another win32 message handler

I want to change the message handler for an old legacy app we use but don't have the source for any more. In a dll that we do have the source for I'm wanting to intercept the window messages and then pass them onto the app. Is this possible? I tried something along the lines of:
WNDPROC lpfnWndProc = NULL;
void GetHandler()
{
HINSTANCE hInstance = GetModuleHandle(NULL);
HWND hWnd = GetActiveWindow();
WCHAR lpClassName[1024];
GetClassName(hWnd,lpClassName,1024);
WNDCLASSEX wc;
GetClassInfoEx(hInstance, lpClassName, &wc);
lpfnWndProc = wc.lpfnWndProc;
wc.lpfnWndProc = NewMessageProc;
RegisterClassEx(&wc);
}
However GetActiveWindow fails and just returns NULL. Is there a simpler way to do this. Infact I'd be happy if I could just simply add another message handler.
It is not clear whether you want to subclass specific controls, or all windows of a particular window class.
If you want to subclass specific controls, the section Subclassing Controls in the MSDN describes how to do this, both for ComCtl32.dll version 6 and above, and the legacy procedure of directly replacing a control's window procedure.
If you want to subclass all controls of a particular window class you would have to change the entries stored in the registered window class, using SetClassLongPtr. Note that this will only affect windows subsequently created with that window class. This is a bit of a Catch 22, as you need to have a window handle when calling SetClassLongPtr, limiting the applicability of subclassing a window class.
As for the code you posted, there are a number of issues:
Your call to GetModuleHandle retrieves the wrong HINSTANCE, namely that of the calling application. Since you need the module handle of the module that registers the window class you have to pass the name of the .dll that implements the controls.
Calling GetActiveWindow may or may not return a value, depending on whether or not the calling thread actually does have an active window. In your case it apparently doesn't, so you need another means of retrieving a window handle, such as FindWindowEx.
Your final call to RegisterClassEx doesn't do what you think: It will simply fail, since you cannot re-register a window class with the same name of an existing window class. You need to call SetClassLongPtr instead, as illustrated above.
I'd actually use SetWindowSubclass after getting the HWND of the window you want to modify the behaviour of. SetWindowLong was deprecated as a way to change the WndProc of a window back around the time that CommCtrl.dll version 6 came out. MSDN can tell you all about that particular part of history and its motivation - just look up SetWindowSubclass.
As it stands, assuming the calling thread has an active window, your code will simply create a new window-class with the same attributes as your target window, albeit with a different WndProc - it wont set the wndproc of an existing window.. - (hence my mention of SetWindowLong and SetWindowSubclass)
EDIT: Or at leaast, it would of not for the oversight I made on that point. As pointed-out in a comment below, this call to RegisterClass will actually fail - you can't register the same className more than once.
You should also probably look at the FindWindow function - just give it a NULL lpWindowName, and the (known) class-name of the target window. In the event that the desired window is not the one that's returned, you could use EnumWindows. Simply call GetClassName in the callback function you supply to EnumWindows, subclassing any/all windows whose class-name matches the class-name of the target window.
Once this window has been subclassed, you can consume its messages as you wish, passing them onto the original window-proc as needed.

MFC DoModal Dialog

Okay, so I will admit I have no knowledge of windows API or even MFC.
I've got an error window popping up when things go hairy (illegal character in a filename string) and I want the error box to be modal.
For the life of me I can't figure out why it crashes when it hits doModal.
Here is the code where I think this can be fixed. This code is in the event handler of a button in the main window.
CDialog *BadFileD = new CDialog();
BadFileD->Create(IDD_STATUS, this);
BadFileD->DoModal();
Am I just being borderline retarded?
MFC dialog divides two pattern, modal dialog and modeless dialog.
(1) Modal dialog usage:
CDialog dlg;
dlg.DoModal();
(2) Modeless dialog usage:
CMyDialog *pDlg = new CMyDialog();
pDlg->Create(ID_DLG, this);
pDlg->ShowWindows(SW_SHOW);
As you can see, we need a new pointer, but do not delete it. So, you need to do the following in our CMyDialog class:
Add DestroyWindow() method in OnOk() and OnCancel().
Add "delete this;" in PostNcDestroy() method.
If you do not, your code may cause a memory leak. BadFileD is a class member, and you delete it in destructor. I suggest use Modeless dialog.
For display modal dialog you should use DoModal method only
CDialog *BadFileD = new CDialog(IDD_STATUS, this);
BadFileD->DoModal();
You can read remarks from article
If you desire to just display an error message, it may be that rather than creating your own dialog you can just use AfxMessageBox(). See Microsoft Developer Network - AfxMessageBox.
If you want to do your own dialog box typically with an MFC project you would normally:
create a dialog box template using the resource editor
create a class encapsulating the dialog box with the class wizard implementing the behavior desired
insert the code to create and display the dialog box into the appropriate place
However with a simple dialog box that requires no supporting class for complex behavior you can skip the step of creating the encapsulating class with the class wizard and just use CDialog directly.
One question that needs to be answered is the lifetime of the dialog as well as whether it is to be modal or modeless. A modal dialog box requires the user to do something for the application to continue past the modal dialog box. A modeless dialog box does not block the application the way a modal dialog box does. There is also a system modal dialog box style.
Since you say it will be a modal dialog then the lifetime will be short so the entire construction, display, and destruction will probably be in a series of lines of code. For instance in a CView class with a command handler displaying a modal dialog box you might have:
void CViewThing::OnCommandMenuItem ()
{
CDialog BadFileD(IDD_STATUS);
int iRetStatus = BadFileD.DoModal();
// check for status such as IDOK, etc.
// do whatever is necessary.
}
What the above does is create a dialog box using the dialog resource template IDD_STATUS and displays it as a modal dialog box. Since it is local object, when the variable BadFileD goes out of scope, the dialog box destructor will be triggered and resources cleaned up for you.
You can also have a modeless dialog box. In the case of a modeless dialog box you need to consider the variable lifetime because as soon as the variable goes out of scope, the destructor will trigger and the dialog box will disappear.
So for a modeless dialog box being used with some view class, perhaps providing a tool box of some kind, the CDialog variable will be a member of the CView class which is using it. After the modeless dialog box is created, it is displayed or not by using the ShowWindow() member function of the CDialog class (actually a member of the CWnd class from which CDialog is derived).
void CViewThing::OnCommandMenuItem ()
{
BadFileD.Create(IDD_STATUS, this);
BadFileD.ShowWindow(SW_SHOW); // display the dialog
}
and in the CViewThing class you would have a member variable CDialog BadFileD;.
Additional considerations
In all of the above examples we are not using pointers so that when the CDialog variable goes out of scope, either from exiting a member function or when the object using the dialog box is destroyed then the dialog box is as well. This object management is done for us.
One thing that you must take into consideration with a modeless dialog box is how to destroy it when you no longer need it.
Since a modal dialog box is usually a short term object, often created as a local variable on the stack, you normally just let it go out of scope to take care of everything dealing with destruction.
However the lifetime of a modeless dialog box requires that the DestroyWindow() method be used to destroy the dialog box when it is no longer needed. See Microsoft Developer Network - Destroying the Dialog Box.
A third usage scenario - embedding a dialog box
There is a third usage of a dialog box that sometimes comes in handy, embedding the dialog box into another window as a control.
In the above examples, the dialog box template specifies the WS_POPUP style for the dialog which is the standard style for a dialog box since the normal way that a dialog box is used is to display as a separate window.
However if you change the WS_POPUP style to WS_CHILD you can then embed the dialog box into another window as a control. You can remove the other style settings such as WS_SYSMENU, DS_MODALFRAME, and WS_CAPTION and remove the CAPTION line from the dialog template to further change the dialog box. So you will end up with something like:
IDD_STATUS DIALOGEX 0, 0, 435, 266
STYLE DS_SETFONT | WS_CHILD
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "this is some static text to display on this dialog.",IDC_STATIC,81,63,200,32
END
Then just use the resulting dialog box similar to how you would a modeless dialog box with ShowWindow().
If you need to reposition the embedded dialog box within its container window, you can use the SetWindowPos() method to do so. For instance the following would move the dialog box window within its containing window to be 20 pixels from the left and 10 pixels from the top of the containing window.
BadFileD.SetWindowPos(NULL, 20, 10, 0, 0, SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER)

Listbox in main window

I'm creating a Win32 GUI application using Code::Blocks and MinGW. I am using this tutorial as a guide. Everything worked well until I decided I needed a listbox to display files in the current directory. I don't want the list box in a window by itself, I want it inside the main window. The tutorial I was following wasn't very helpful on this part, so I still don't know how to create a listbox. Using the resource editor somehow, I think. Could someone please help me?
I assume you have a window procedure somewhere (let's call it WndProc) for your main window (let's call it hWndMain).
Add a WM_CREATE handler in WndProc if it's not already there.
In the WM_CREATE handler, add a call to CreateWindowEx to create the listbox as a child window of hWndMain:
const HWND hWndList = CreateWindowEx(...);
The picky parameters of CreateWindowEx that are essential here are the class name "LISTBOX", that the style parameter must include the WS_CHILD flag (plus the other essential listbox flags, of course) and that the parent parameter must be hWndMain.
For the other parameters, use your brain and read the docs.