Changing window procedure for console window - c

I want to make console window with a functional tray icon. I figured out that most probably it is necessary to replace initial console's window procedure so I will be able to control all messages including notify area events. But SetWindowLong() function returns 0, and GetLastError() tells that access is denied.
hwndFound = GetConsoleWindow();
SetWindowLong(hwndFound, GWL_WNDPROC, (long)WndProc);
What could it be, or maybe there is some other way to control tray icon manipulations?

If all you want to do is create a notification icon for a console application, there's nothing that says your Shell_NotifyIcon call has to point to the console window. Create an invisible dummy window with your own window class and procedure instead. Note that you'll probably have to do this from a secondary thread in order to run its message loop. (The console window is special, as it's hosted outside your process by conhost.exe/csrss.exe.)

No, you just need a window. Best thing is to startup a thread so you can pump a message loop and receive the icon notifications. Create a little hidden window that you can use for the Shell_NotifyIcon() call.

Which version of Windows are you using? I know that prior to Vista, console windows are treated specially, and can't be manipulated in many of the standard ways. This article by Raymond Chen might shed some further light.

Related

Is there something like CDN_FILECANCEL analogous to CDN_FILEOK for getting when the user chooses Cancel in GetOpenFileName()?

For cross-platform parity reasons, my GetOpenFileName() specifies no owner and I explicitly disable all toplevel windows myself. The problem is re-enabling. In order to re-enable these windows correctly, I need to re-enable them before the dialog closes.
In the case of the user choosing a file, this is no issue: I just check for CDN_FILEOK in the hook procedure. No issues, no messed-up focus.
How can I do the same, but for cancelling the dialog box?
I have tried WM_DESTROY in the hook procedure, but that runs after the dialog box has been hidden (too late). I have tried WM_COMMAND, but that doesn't seem to cover all cases. I'm not sure what other options I have.
I need to target Windows XP and newer for now; that also means no Common Item Dialogs. Thanks!
Alternative: if there was a way to do a callback-based GetOpenFileName() that returned control to my message loop, like on Mac OS X with beginSheetModalForWindow:, I could be able to specify a parent window and avoid this hack.
There is no CDN notification when the dialog is canceled. If the user presses the Cancel button, you could try intercepting the BN_CLICKED notification that it sends to the dialog, or even subclass the button itself. But if the user cancels the dialog through other means (clicking the red X, pressing ESC, etc), you will likely have to catch the WM_CLOSE message instead.

multiple windows, single tray icon

My goal is to have a single icon for all the windows of my application.
After some reading, my understanding is that creating a tray icon is achieved through Shell_NotifyIcon(). This function gets a NOTIFYICONDATA structure which contains a hWnd field. This HWND is used by the system to notify the corresponding window of tray icon events. These events are handled by a WindowProc callback that is set on the window with SetWindowLongPtr().
Hence my questions:
How can a single icon notify all the windows of my app of say a left mouse click ?
Can I Shell_NotifyIcon() multiple times with different NOTIFYICONDATA structures, each one with a different hWnd, but with the same icon ?
What if the original window that got registered for creating the tray icon is destroyed ?
Would creating a hidden proxy window be an appropriate solution ?
Some background: my application calls the WinAPI with C (using js-ctypes), and should ideally work on all Windows versions from XP on.
You practically answered your own question in the question itself. The best thing to do is create a hidden window that survives as long as you need the tray icon to exist.
You would call Shell_NotifyIcon() only once with the hWnd referring to this hidden window, and have this window post the messages to the individual windows that need to receive them.
This also gives you the flexibility of being able to decide to skip sending messages to a particular window, or being able to send a different message to each window, depending on the requirements of your particular application.

Launch WPF executable and set parent?

I have a WPF executable and I want another program to launch it and set this launching program as the parent windows of my WPF executable (The main purpose is that when the launching program is closed the WPF executable is also shut down). I thought I could make it like this: I pass the Hwnd as one command line parameter (as integer-string), and I can call the SetParent or whatever function inside my WPF executable code to specify the parent. However, I can't make it work. Can anybody tell me how to do that, or any other way to do that? Thanks!
You can't. Window handles are per-process.
Besides, you wouldn't want to. It's problematic enough to have a parent window in another thread -- that causes the message queues of the two threads to become attached, i.e., they effetively share the same message queue from then on. So now if either thread locks up, or does some lengthy processing, both threads are frozen. (And there's no way to later detach the message queues, as far as I'm aware.) Imagine trying to extend this cross-process.
If you must start some new code and use an existing window as a parent, you can't go cross-process. You would have to load the WPF code into your process and call a method in it, passing your parent window as a parameter. The simplest way to load that code into your process would be to change your WPF application to a class library (.dll), and either add a reference to that .dll, or load it dynamically using Reflection.
As #Joe White said you cannot achieve this straightaway ... I think I can "guess" what you are getting at ....
You probably have a WinForm MDI parent (its exe already) and you want to launch another WPF window (another exe) as its child. Am I correct?
Hmmmm then you would have to create a new WinForm child window with WinFormWPFHostApp in it and then refer the WPF assemblies to this project and try to host the Content of the MainWindow from that other WPF application.
refer this article...

How to let the parent window of a child window (a.k.a. owned window) stay active with winapi?

I am writing a small C application using winapi. There I've got a window with a child window (toolbox). I am able to keep it inside this window and so on, but my question is: How to keep the main window active, if the child window gets focused?
The main window gets grayed out in this moment.
The windows get created by:
hMainWindow = DialogBoxParam(.......);
hChildWindow = CreateDialogParam(..., hMainWindow, ...);
ShowWindow (hChildWindow, SW_SHOW);
Here a little image of the behaviour of the two windows:
I've found out that simply creating it as WS_CHILD and explicitly NOT as WS_POPUP solves that. It also turns the absolute window coordinates to relative ones so that I dont have to care about the window position anymore by moving the parent window.
// Solved
Create the child window as a modeless dialog box instead of a modal one. So instead of using DialogBox, use CreateDialog
Sorry, that's just the way Windows works: one active window at a time.
You can see this in Visual Studio if you bring up Find and Replace as a tool window, you'll see that it gets activated and the main VS window goes inactive.
Trying to have them both active at the same time could confuse users and accessibility tools like screen readers.

Form.Show not showing up in Taskbar in Vista

I have a winform app that is hiding it's UI and waiting on a named pipe message before showing up
On receiving the event the thread invokes into the main UI thread and then does the following
Set the opacity to 100
ShowInTaskbar = true;
BringToFront();
ON Windows Vista the window does not show up on the taskbar though and the window is in the background . YOu cant say it
if you finally find it and click on it, it shows up on the taskbar
any ideas on how to fix this
i don't work in vista but it might be better just to flash the taskbar or do a ballon popup or something like that. What your suggesting maybe a bit annoying to a user. Say there typing away and there looking at the keyboard and your window has stolen the focus they look back and find what they just wrote hasn't gone into the app they thought it was going into.like this.
flashing the task bar
this might help also
If the form has an Owner set it might or might not show up in the taskbar.
Don't set the Owner property and it should show fine (it did for me).

Resources