How to create multiple instances of the same Dialog Procedure in win32? - c

Within a modeless DialogBoxProcedure(), I implemented two main functions:
Constant movement along the X and Y axis using SetWindowPos(), each movement activated by a timer. (Essentially making the Dialog Box bounce around the screen). I did this by using static int to set the variables, and adjust them accordingly upon receiving a new timer message.
Recursively Creating a new DialogBox by calling CreateDialog() whenever the original Dialog Box receives the appropriate message to do so.
I wanted the new recursively created dialog box to call on its own DialogBoxProcedure with its own set of static variables so it could move independently, but what ended up happening was the new DialogBox was stacked exactly on top of the previous dialog box,probably because of the usage of static variables in the DialogProcedure. Is there a way to fix this?

You can't create multiple instances of the same dialog procedure. You can use the same dialog procedure more than once and make sure it knows which dialog it's talking about.
Store the variables in some kind of structure and make two instances of that, for example using malloc or just two different global or static variables.
Then:
Instead of CreateDialog use CreateDialogParam and give it a pointer:
// instead of
hWndDialog = CreateDialog( hInstance, IDD_MY_DIALOG, hWndParent, MyDialogProc);
// use:
hWndDialog = CreateDialogParam(hInstance, IDD_MY_DIALOG, hWndParent, MyDialogProc, pMyDialogStruct1);
// ^^^^^ ^^^^^^^^^^^^^^^^
When your dialog proc gets a WM_INITDIALOG message, that pointer is in lParam. You can then transfer it to the HWND by using SetWindowLongPtr(DWLP_USER):
SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)lParam);
Now the struct pointer is stored in the HWND and you can get it back at any time:
MyDialogStruct* dlgStruct = (MyDialogStruct*)GetWindowLongPtr(hWnd, DWLP_USER);

Related

Initialization of GtkApplication - Should I use GObject's "init" or GtkApplication's "startup"?

I'm trying to create a GTK-3 Application and in the initialization process I want to check if the GSetting's value is set, otherwise I want to show a "startup" dialog which will be only on the first run visible.
The GObject's has a _init suffix which can be used for the class initialization. In that case the MyGtkApplication will be constructed, which is based on GtkApplication. The GtkApplication has the startup-thing which can be used for the initialization too.
In that example, I still need to implement the _init function for GApplicationClass.
GApplicationClass *gapp_class;
gapp_class = G_APPLICATION_CLASS (class);
gapp_class->startup = app_startup;
// This must be always implemented, because the MyGtkApplication is "GtkApplication"-based class.
void app_init(MyGtkApplication *app) {
// Check and show the modal dialog if key does not exist?
}
// This will overwrite the GApplicatio's "startup".
void app_startup(GApplication *app) {
// Check and show the modal dialog if key does not exist?
}
Currently app_init does not have a body.
What is the difference and which one should I use?
Regards,
TheAifam5.
init is basically the constructor of the GApplication object. Use it for initializing the object's private data and putting it into a consistent state.
startup is invoked when the application starts. In particular, after you have called g_application_run() and the main event loop is started, and the application has checked that it is the only instance running. You don't want to show dialog boxes before then, so startup is the right place to do that.

Win32 - A better way to intercept a window before it is created

I am trying to automate an external Windows application. The goal is to make this application start minimized without showing any active window/splash screens and without stealing focus from other applications.
I wrote a little program on C that calls EnumWindows() in a loop and uses ShowWindow() to minimize the required window. It is quite fast and works in 80% of cases. Unfortunately, sometimes the application window is still showing and stealing the focus for a short period of time.
What would be a better (sure) way to intercept the window?
Is using SetWindowsHookEx hooks the only alternative?
Have you tried using the wShowWindow member of the STARTUPINFO structure you pass to CreateProcess() when starting the application? That was designed to do exactly things like this.
If dwFlags specifies STARTF_USESHOWWINDOW, this member can be any of the values that can be specified in the nCmdShow parameter for the ShowWindow function, except for SW_SHOWDEFAULT. Otherwise, this member is ignored.
For GUI processes, the first time ShowWindow is called, its nCmdShow parameter is ignored wShowWindow specifies the default value. In subsequent calls to ShowWindow, the wShowWindow member is used if the nCmdShow parameter of ShowWindow is set to SW_SHOWDEFAULT.
For example:
STARTUPINFO si = { sizeof(si) }
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_MINIMIZE;
CreateProcess(..., &si, ...);

Gtk and C - Multi-threaded GUI Application and Removing Global Variables

I have the example GTK C application from [1] building and working as expected. I have a pretty little UI application with a + and - button to increment/decrement a value stored in a global variable, and render it in the application in a text label.
I rarely ever work with GUI applications, and I do 99% of my work in C. I have two key questions with respect to tidying up this example and using it as the basis of a project.
Is it possible to have some alternative to global variables, like a
custom struct I create in main(), and have every callback handler reference
it by changing the function protocol for increase()?
Code:
// Can this function protocol be modified?
void increase(GtkWidget *widget, gpointer label) {
count++;
sprintf(buf, "%d", count);
gtk_label_set_text(GTK_LABEL(label), buf);
}
g_signal_connect(minus, "clicked", G_CALLBACK(decrease), label);
Is there a simple means of creating a separate thread to help manage the GUI? For example, if I have a button tied/connected to a function that would take a minute to complete, is there a universally-accepted means of firing off a separate pthread that allows me to have a button or command to cancel the operation, rather than the entire UI app being blocked for the whole minute?
Thank you.
References
Cross Compiling GTK applications For the Raspberry Pi, Accessed 2014-02-20, <http://hertaville.com/2013/07/19/cross-compiling-gtk-applications-for-the-raspberry-pi/>
Yes, you can pass anything you like as the last argument to signal handlers (gpointer is a typedef for void*) just create the structure containing the label widget and the counter variable in main(), pass it as the last argument to g_signal_connect and cast it back to the proper type in your callback.
For running a calculation in another thread and delivering the result to the gtk main loop I'd look at GTask, in particular g_task_run_in_thread_async.

how to get CREATESTRUCT of a window?

I am trying to make a windows GUI application.
I declared some static variables in my window procedure function and initialized it in the WM_CREATE whose lParam is a pointer to the CREATESTRUCT. However, since these values are static, I can only make one instance of my window; if I make more the previous instances' data will be changed to the new datas.
Is there a way to access the CREATESTRUCT of a window after the WM_CREATE message so that I can solve this problem?
Save a pointer to a user-defined structure in WM_CREATE using either SetWindowLongPtr or SetProp, and retrieve it with the matching functions.
e.g.
case WM_CREATE:
SetWindowLongPtr(hWnd, GWLP_USERDATA, ((LPCREATESTRUCT)lParam)->lpCreateParams);
break;
case <other messages>:
MyData* pData = (MyData*)GetWindowLongPtr(hWnd, GWLP_USERDATA).
Some will argue that you shouldn't use GWLP_USERDATA and instead should reserve storage space in your window class; this is up to you. Using SetProp/GetProp is also a valid alternative.

Win32 C API for redirecting minimize animation

I have seen RocketDock redirect the minimize animation in Vista so windows minimize to the dock, and am just curious how this was done. Is the actual minimize animation redirected to the dock, or is something like a hook to stop Windows from minimizing the window and RocketDock has a custom animation when the window is minimized?
I am working on an open source multi-monitor taskbar project called "OpenMMT." I've recently discovered (through many headaches) how to accomplish this.
The following explanation assumes that you know how to go about using RegisterShellHookWindow.
On the window procedure that will receive the shell hooks, look for HSHELL_GETMINRECT.
Now, from here on out is where I had problems. According to MSDN, the lparam member passed contains a pointer to a "SHELLHOOK" object. Which is true, however, I could not get it to work for the simple fact that the "rc" member of that structure, is a RECT that differs from the actual RECT structure in the Windows header files. The RECT in the header files uses LONG for its members, were as on here, we want SHORT.
Anyways, here's a snippet on how I accomplished this.
Structures to define:
typedef struct {
SHORT left;
SHORT top;
SHORT right;
SHORT bottom;
} REALRECT, *LPREALRECT;
typedef struct {
HWND hWnd;
REALRECT rc;
} DOCUMENT_ME_RIGHT_MICROSOFT, *LPDOCUMENT_ME_RIGHT_MICROSOFT;
Then on the Window Procedure:
case HSHELL_GETMINRECT:
{
LPDOCUMENT_ME_RIGHT_MICROSOFT lpShellHook = (LPDOCUMENT_ME_RIGHT_MICROSOFT)lParam;
// lpShellHook now contains all the info. If you want to change the location
// of the animation, simply change the lpShellHook->rc members to point
// to the right coordinates and then return TRUE;
return TRUE;
}
When minimizing programs from my application I encountered some instances where the animation would default back to the original one. I resolved this by minimizing them like so:
void MinimizeApp(HWND hWnd) {
SetForegroundWindow(hWnd);
ShowWindowAsync(hWnd, SW_MINIMIZE);
}
If you want more info regarding my project or you just want to peek at the source, feel free to do so at https://github.com/Fafson/OpenMMT
The ptMinPosition member of the WINDOWPLACEMENT structure specifies the coordinates of the window when it is minimized, so SetWindowPlacement function can be used to that effect. But some testing shows the window should not have a task bar button for that to work (i.e. no WS_EX_APPWINDOW).
I don't know how RocketDock works, but I guess this could be achieved by installing a global WH_CBT hook, and acting upon (setting the ex_style and then setting minimized coordinates) HCBT_MINMAX notification.
You can use the AnimateWindow API function, and pass it e.g. AW_HOR_POSITIVE | AW_VER_POSITIVE to get a diagonal animation.
I'd start with a global hook catching WM_SYSCOMMAND/SC_MINIMIZE, and use AnimateWindow to target the top right corner.
If this doesn't provide the desired effect, the next step would be to use WM_PRINT/WM_PRINTCLIENT to get a copy of the window into a bitmap (I believe this is what AnimateWindow does internally), then hiding the window and doing my own animation.

Resources