Structuring Win32 GUI code - c

I wish to improve my code and file structure in larger Win32 projects with plenty of windows and controls. Currently, I tend to have one header and one source file for the entire implementation of a window or dialog. This works fine for small projects, but now it has come to the point where these implementations are starting to reach 1000-2000 lines, which is tedious to browse.
A typical source file of mine looks like this:
static LRESULT CALLBACK on_create(const HWND hwnd, WPARAM wp, LPARAM lp) {
setup_menu(hwnd);
setup_list(hwnd);
setup_context_menu(hwnd);
/* clip */
return 0;
}
static LRESULT CALLBACK on_notify(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
const NMHDR* header = (const NMHDR*)lp;
/* At this point I feel that the control's event handlers doesn't
* necessarily belong in the same source file. Perhaps I could move
* each control's creation code and event handlers into a separate
* source file? Good practice or cause of confusion? */
switch (header->idFrom) {
case IDC_WINDOW_LIST:
switch (header->code) {
case NM_RCLICK:
return on_window_list_right_click(hwnd, wp, lp);
/* clip */
}
}
}
static LRESULT CALLBACK wndmain_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
switch (msg) {
case WM_CREATE:
return on_create(hwnd, wp, lp);
case WM_CLOSE:
return on_close(hwnd, wp, lp);
case WM_NOTIFY:
return on_notify(hwnd, wp, lp);
/* It doesn't matter much how the window proc looks as it just forwards
* events to the appropriate handler. */
/* clip */
default:
return DefWindowProc(hwnd, msg, wp, lp);
}
}
But now as the window has a lot more controls, and these controls in turn have their own message handlers, and then there's the menu click handlers, and so on... I'm getting lost, and I really need advice on how to structure this mess up in a good and sensible way.
I have tried to find good open source examples of structuring Win32 code, but I just get more confused since there are hundreds of files, and within each of these files that seem GUI related, the Win32 GUI code seems so far encapsulated away. And when I finally find a CreateWindowEx statement, the window proc is nowhere to be found.
Any advice on how to structure all the code while remaining sane would be greatly appreciated.
Thanks!
I don't wish to use any libraries or frameworks as I find the Win32 API interesting and valuable for learning.
Any insight into how you structure your own GUI code could perhaps serve as inspiration.

For starters, I'd take a look at the message crackers in windowsx.h; they'll save you writing tedious case statements in your window procedures, and they suggest a certain discipline in function names.

Related

Is calling a function faster than SendMessage()?

Is calling a function that does the same thing as the message you're sending faster than calling SendMessage()?
For example in the code below in case WM_RBUTTONUP:, which is faster, calling EnableTwoWindows(firstWnd, secondWnd);or sending SendMessage(hwnd, CUSTOM_MESSAGE_ENABLE_TWO_WINDOWS, 0, 0);? And what are the advantages and disadvantages of calling a function vs sending a message?
void EnableTwoWindows(HWND hwnd1, HWND hwnd2)
{
EnableWindow(hwnd1, TRUE);
EnableWindow(hwnd2, TRUE);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HWND firstWnd, secondWnd;
switch(msg)
{
case CUSTOM_MESSAGE_ENABLE_TWO_WINDOWS:
EnableWindow(firstWnd, TRUE);
EnableWindow(secondWnd, TRUE);
break;
case WM_RBUTTONUP:
//EnableTwoWindows(firstWnd, secondWnd); //Is calling this function faster? or
//SendMessage(hwnd, CUSTOM_MESSAGE_ENABLE_TWO_WINDOWS, 0, 0); //Is sending message faster?
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
Calling the function directly is faster than going through a SendMessage call.
This can be easily inferred, when you look at what SendMessage does: It first needs to determine, whether the target window is owned by the same thread, and if so, retrieve the window procedure, and finally call that.
If the target window is owned by another thread, it gets more costly, as the SendMessage call has to queue up the message on the target thread's queue, wait for it to invoke a message retrieval function, and can only return, when the target thread has dispatched the message and produced a return value. In that case, however, it is mandatory to call SendMessage. Manipulating windows from threads other than the owning thread results in undefined behavior. SendMessage ensures, that the manipulations run on the same thread, that owns the window.
In addition, the compiler can inline the direct function call. This is not possible when calling SendMessage, since the compiler cannot see its implementation.
Performance is not an issue: You are responding to user input. The user is the bottleneck. Correctness, on the other hand, is essential. If you need to decide, use the following rule: If the windows you are manipulating are owned by a thread other than the calling thread, use SendMessage. If the windows are owned by the calling thread, go for a direct function call.
Yes.
It costs more to call multiple functions than it does to call one function.

Disable mouse promotion

Is there any way to disable mouse promotion from code, that is preventing windows to interpret touch events as mouse events?
I capture touch events in my WPF application, and I don't want these interactions to effect mouse pointer visibility and position.
There is a TouchFrameEventArgs.SuspendMousePromotionUntilTouchUp Method that seems to be doing exactly that. Unfortunately it's available only for Silverlight and Windows Phone.
In addition there are some system settings you can use to disable double click and right click promotion, but nothing to disable mouse promotion as a whole.
A Windows 8 specific solution or a low level solution would also help.
The plain Win32 API way of disabling touch promotion to mouse is to handle WM_POINTER* messages in your window's WindowProc (actually, it seems just WM_POINTERDOWN is enough) and NOT call DefWindowProc().
This is what we actually do in some of our commercial applications, and what is suggested here.
This is ONLY available from Windows 8 and later, since the WM_POINTER* messages are not generated by Windows 7 and below.
Now, in the WPF world, this gets more complicated.
First of all, in order to get proper WM_POINTER* handling by the WPF stack, you first need to
Use .NET 4.7
Change some configuration in your WPF app:
(Reporting the code here, just in case the MS page disappears) You need to insert this in your app.config file:
<configuration>
<runtime>
<AppContextSwitchOverrides value="Switch.System.Windows.Input.Stylus.EnablePointerSupport=true"/>
</runtime>
</configuration>
Now the new shiny WPF stack is activated, but it's bugged and moves the mouse cursor even if you handle the OnTouchDown, OnTouchUp, OnTouchMove events and set the Handled flag to true.
We discovered, through the use of a HwndSourceHook and blocking the WM_POINTERDOWN message, that the mouse cursor was finally staying still (although we were blocking all touch-down interactions!)
So, we deducted that the shiny new WPF is actually calling DefWindowProc, even if we are handling the OnTouch* events.
Our soultion was to use Microsoft Detours, in order to intercept the DefWindowProc call, and block the WM_POINTERDOWN from reaching the real DefWindowProc.
The detour code is:
#include <Windows.h>
#include <detours.h>
static LRESULT(WINAPI * _originalDefWindowProcA)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) = DefWindowProcA;
static LRESULT(WINAPI * _originalDefWindowProcW)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) = DefWindowProcW;
static LRESULT WINAPI myDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_POINTERDOWN:
return 0;
default:
return _originalDefWindowProcA(hWnd, Msg, wParam, lParam);
}
}
static LRESULT WINAPI myDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_POINTERDOWN:
return 0;
default:
return _originalDefWindowProcW(hWnd, Msg, wParam, lParam);
}
}
void SetupDefWindowProcDetour()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)_originalDefWindowProcA, myDefWindowProcA);
DetourAttach(&(PVOID&)_originalDefWindowProcW, myDefWindowProcW);
DetourTransactionCommit();
}
NOTE: SetupDefWindowProcDetour must be called by the main (UI) thread of your app.
public static class PreventTouchToMousePromotion
{
public static void Register(FrameworkElement root)
{
root.PreviewMouseDown += Evaluate;
root.PreviewMouseMove += Evaluate;
root.PreviewMouseUp += Evaluate;
}
private static void Evaluate(object sender, MouseEventArgs e)
{
if (e.StylusDevice != null)
{
e.Handled = true;
}
}
}
Excample Usage:
public MainWindow()
{
InitializeComponent();
PreventTouchToMousePromotion.Register(this);
}
or take a look at this post
http://social.msdn.microsoft.com/Forums/vstudio/en-US/9b05e550-19c0-46a2-b19c-40f40c8bf0ec/prevent-a-wpf-application-to-interpret-touch-events-as-mouse-events?forum=wpf#9965f159-04a4-41ed-b199-30394991f120
There doesn't seem to be any such option (at least up to Windows 8.1 and .NET 4.5).
The only way to disable mouse promotion is to disable finger input completely, either from within the system control panel (open control panel, open "Pen and Touch", select "Touch" tab, disbale "Use your finger as an input device") or via Registry (HKLM\Software\Microsoft\Wisp\Touch, TouchGate = 0 =disable touch)
Then you can still process touch input using one of the following (nasty) alternatives:
Write your own WinUSB driver for your touch device
Get raw touch input data using the RawInput API
Find a 3rd party USB driver for your device (e.g. UPDD TouchBase)
Finally, you can inject the collected touch data into your application using custom routed events or using touch injection.
In any case you will, of course, loose touch support for any other application on your system, so this solution will in general not be too helpfull to you.

Are there any good options for creating functional windows forms for C?

I have been learning C# and use Microsoft Visual Studio which makes it very easy and enjoyable to create windows forms with various controls like progress bars, drop down menus, file-system browsers etc..
Can the same thing be done with C, and are there any recommended programs?
(I have learned some C and would like to make graphical interfaces a step further than just in the console, I guess this is quite hard?).
The windows API was (and still is) a C API. Documented on msdn.microsoft.com.
The simplest way to create a Windows application with a simple form, in C, without using any external frameworks is this program:
#include <Windows.h>
#include "Resource.h"
BOOL CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hNull, LPTSTR cmdLine, int cmdShow)
{
return DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_MAINDIALOG),NULL,DialogProc,0L);
}
The assumption is that, in addition to this main.c file, you use the Visual Studio resource editor to create a resource script file (.rc) with a dialog resource that you lay out your controls on.
If you are using Visual Studio Express a resource editor is not included and you will need a 3rd party editor (they are available) to lay out the dialog.
GTK+ at http://www.gtk.org/documentation.php

global keyboard hooks in c

i want to write a global keyboard hook to disallow task switching.When i googled i found a whole lot of codes in c#,cpp (and delphi), but i need some basic concepts about hooking (would be the best if examples are in C).So, kindly suggest the resources,links that can help me understand the thing in C's perspective.
PS: I found one good working example(works on winXP and older versions),but when i tried compiling the code it gives me:
And i tried searching the "IDC_" constants in all the headers(default ones that come with MinGW gcc installation and the ones provided by developer),but no luck...If any one can compile the code and make it run please help me.I have not uploaded the source itself here as there are a few header file dependencies and in that case i'd have to post all the code here.
winXP is the target environment but would be better if i get it to run Win7 also.
I will go out on a limb here assuming you are on Windows and you want to capture global keystrokes. A way to do this is to use LowLevelHooks. Look at the following example:
Define this callback function somewhere in your code:
//The function that implements the key logging functionality
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
{
char pressedKey;
// Declare a pointer to the KBDLLHOOKSTRUCTdsad
KBDLLHOOKSTRUCT *pKeyBoard = (KBDLLHOOKSTRUCT *)lParam;
switch( wParam )
{
case WM_KEYUP: // When the key has been pressed and released
{
//get the key code
pressedKey = (char)pKeyBoard->vkCode;
}
break;
default:
return CallNextHookEx( NULL, nCode, wParam, lParam );
break;
}
//do something with the pressed key here
....
//according to winapi all functions which implement a hook must return by calling next hook
return CallNextHookEx( NULL, nCode, wParam, lParam);
}
And then somewhere inside your main function you would set the hook like so:
//Retrieve the applications instance
HINSTANCE instance = GetModuleHandle(NULL);
//Set a global Windows Hook to capture keystrokes using the function declared above
HHOOK test1 = SetWindowsHookEx( WH_KEYBOARD_LL, LowLevelKeyboardProc, instance,0);
More general information about hooks can be found here.
You can also capture other global events with the same exact way only following the directions given in SetWindowsHooksEX documentation.

Hook keyboard from injected DLL using KeyboardProc / SetWindowsHookEx

Note: I am working in plain C. Not C++, not C#.
I am working on a mod. I've already written a working DLL-injector, as well as the DLL to be injected. Everything is going well, apart from the userinput.
I want to be able to use hotkeys, so I tried to setup a keyboardhook using SetWindowsHookEx.
The following is my callback function:
LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
{
printf("key touched\n");
if (wParam == VK_F5)
{
keyEvent = VK_F5;
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
And this is how I set it up:
HHOOK kbHookHandle = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)keyboardHook, NULL, GetCurrentThreadId());
if (kbHookHandle != NULL)
{
printf("keyboard hook successful!\n");
}
else
{
printf("keyboard hook failed!\n");
}
As far as I can tell, the hook gets setup well (I used to have a problem with an invalid parameter, but fixed that by using GetCurrentThreadID). It returns a handle which is not NULL.
But whenever I press a key, there is no output.
To further clarify:
The code above is from the injected DLL. So it effectively 'belongs' to the game process. I have allocated a console using AllocConsole, to print debug messages to.
What am I doing wrong?
EDIT:
To clarify (even more): the listed code is from the injected DLL. It is not the approach I use to inject the DLL - I wrote a seperate (working!) program to do just that.
It surprises some that I use printf(), since that wouldn't show up, considering I call it from inside the host process. Yes, I do call it from inside the host process, but that is not an issue, because I have already allocated a working console. I used an approach very similar to the one mentioned here
EDIT2:
I am not asking why printf() isn't working (because it is), I am asking why this keyboardhook isn't working.
Here's how I detect key down and key up in my NoQuake ID Tech games minimizer. Hope it helps.

Resources