How do I know when window is created? - c

How can I check if window is already created? I tried this
BOOL isWindowReady = FALSE;
while(!isWindowReady)
{
hwnd = FindWindow(windowClass, NULL);
if (hwnd == NULL) {
hwnd = FindWindow(windowClass, NULL);
}
else {
isWindowReady = TRUE;
}
}
but id doesn't work.

Your code is technically fine (though your second call to FindWindow() is redundant) - provided you are supplying the correct value for windowClass, that is.
That being said, your loop can be simplified:
while (!FindWindow(windowClass, NULL)) { Sleep(100); }
Or, if you need the HWND to access the window later:
HWND hWindow;
do
{
hWindow = FindWindow(windowClass, NULL);
if (hWindow) break;
Sleep(100);
}
while (true);

Related

How to get the process name based on hwnd in C

Programming language: C
Objective: Get the process id and name based on the current hwnd.
Current code:
HWND hwnd;
DWORD process_ID;
PWSTR process_name = NULL;
hwnd = GetForegroundWindow();
process_ID = GetWindowThreadProcessId(hwnd,&process_ID)
process_name = ????
I am not sure if I am passing correctly the arguments to the function GetWindowThreadProcessId. I found on Internet that I could use GetModuleFileNameW to get the process name but I cannot understand the documentation. Please forgive me if it is too easy to solve. I am starting in the world of C. Thanks in advance
The return value of GetWindowThreadProcessId() is a thread ID, not a process ID, so DO NOT assign that return value to your process_ID variable, or else it will overwrite the value that was output by the lpdwProcessId parameter.
HWND hwnd = GetForegroundWindow();
DWORD process_ID = 0;
if (GetWindowThreadProcessId(hwnd, &process_ID))
{
// get the process name ...
}
else
{
// error handling ...
}
Once you have the process ID, you can pass it to OpenProcess() to get a HANDLE to the running process, and then use that HANDLE with either GetModuleFileNameEx(), GetProcessImageFileName() (XP+), or QueryFullProcessImageName() (Vista+) to get the full path and filename of that process's EXE file:
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_ID);
if (hProcess)
{
WCHAR process_name[MAX_PATH] = {};
if (GetModuleFileNameExW(hProcess, NULL, process_name, MAX_PATH))
{
// use process_name as needed...
}
else
{
// error handling ...
}
CloseHandle(hProcess);
}
else
{
// error handling ...
}
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_ID);
if (hProcess)
{
WCHAR process_name[MAX_PATH] = {};
if (GetProcessImageFileNameW(hProcess, process_name, MAX_PATH))
{
// use process_name as needed...
}
else
{
// error handling ...
}
CloseHandle(hProcess);
}
else
{
// error handling ...
}
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_ID);
if (hProcess)
{
WCHAR process_name[MAX_PATH] = {};
DWORD size = MAX_PATH;
if (QueryFullProcessImageNameW(hProcess, 0, process_name, &size))
{
// use process_name as needed...
}
else
{
// error handling ...
}
CloseHandle(hProcess);
}
else
{
// error handling ...
}

Custom WM_APP message isn't posted in the message queue

I am trying to send a custom message (WM_APP + 1) when WM_SIZE is send to the window procedure. I want to be able to catch it from an other function using PeekMessage and do somethings. But when I test it the messages seem to not be send to the queue. Adding some printf statements shows me that it goes to the window procedure. The weird thing is that when I step through the code in the debugger it works fine but when I'm running normally, it goes back to not working.
Working example program with the problem, resize the window to test:
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "user32.lib")
#define OBG_EVENT_QUIT 0
#define OBG_EVENT_RESIZE 1
#define OBG_EVENT_NO -1
#define OBG_EVENT_UNKNOWN -2
//user defined event
#define OBG_WM_RESIZE (WM_APP + 1)
typedef union
{
int type;
struct
{
int type;
int width;
int height;
} resizeEvent;
} obg_event;
LRESULT CALLBACK obgpf_DefaultWindowCallback(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
switch(message)
{
case WM_CLOSE:
{
PostMessageA(window, WM_QUIT, 0, 0);
} break;
//this should be handled by OBGGetEvent
case OBG_WM_RESIZE:
{
printf("MESSAGE WENT THROUGH. DON'T WANT THIS\n");
} break;
case WM_SIZE:
{
PostMessageA(window, OBG_WM_RESIZE, wParam, lParam);
} break;
default:
{
result = DefWindowProc(window, message, wParam, lParam);
} break;
}
return result;
}
int OBGGetEvent(obg_event *event)
{
int moreMessages = 0;
MSG message;
if(PeekMessage(&message, 0, 0, 0, PM_REMOVE))
{
moreMessages = 1;
switch(message.message)
{
case WM_QUIT:
{
event->type = OBG_EVENT_QUIT;
} break;
case OBG_WM_RESIZE:
{
event->type = OBG_EVENT_RESIZE;
event->resizeEvent.type = OBG_EVENT_RESIZE;
event->resizeEvent.width = LOWORD(message.lParam);
event->resizeEvent.height = HIWORD(message.lParam);
} break;
default:
{
event->type = OBG_EVENT_UNKNOWN;
TranslateMessage(&message);
DispatchMessage(&message);
} break;
}
}
else
{
event->type = OBG_EVENT_NO;
}
return moreMessages;
}
int main()
{
HINSTANCE instance = GetModuleHandleA(0);
WNDCLASSEX windowClass = {0};
windowClass.cbSize = sizeof(windowClass);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = obgpf_DefaultWindowCallback;
windowClass.hInstance = instance;
windowClass.lpszClassName = "testClass";
windowClass.hIcon = LoadIcon(0, IDI_APPLICATION);
windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
windowClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
windowClass.hCursor = LoadCursorA(0, IDC_ARROW);
HWND window;
if(RegisterClassEx(&windowClass))
{
window = CreateWindowEx(0,
windowClass.lpszClassName,
"test window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
500,
300,
0,
0,
instance,
0);
if(window)
{
int appIsRunning = 1;
obg_event event = {0};
event.type = -1;
while(appIsRunning)
{
while(OBGGetEvent(&event))
{
if(event.type == OBG_EVENT_QUIT)
{
printf("event quit\n");
appIsRunning = 0;
break;
}
else if(event.type == OBG_EVENT_RESIZE)
{
printf("window resized: width %d height %d\n", event.resizeEvent.width, event.resizeEvent.height);
}
}
Sleep(33);
}
}
else
{
printf("window error\n");
}
}
else
{
printf("windowClass error\n");
}
return 0;
}
I tried doing this with SendMessage instead of PeekMessage but the same thing happened. Not sure what I'm missing or misunderstanding but any help is appreciated!
EDIT: added a complete working program that reproduces the problem
Thank you for the example code.
The behaviour you're seeing is because when the window is being resized using the mouse, the OS enters a modal message loop to process mouse input. During this loop, your message loop doesn't run - which means your PeekMessage() and the special message handling doesn't run either. Instead, messages are simply dispatched as normal to your window procedure.
There are two solutions that come to mind immediately but how you deal with this really depends on the design of your program and why you want to process size events in this way.
The first idea I had is to keep track of whether you're in a modal sizing loop or not, and defer posting the notification message until the loop is finished. An example of how to do that using your provided window procedure is below.
The second solution is to simply call your resize event handler directly whenever you get WM_SIZE (or, if you must go through the event system, put the handler for it in the window procedure rather than using PostMessage).
Example code for the first suggestion:
LRESULT CALLBACK obgpf_DefaultWindowCallback(HWND window, UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0;
static bool fResized = false;
static bool fInSizeLoop = false;
switch(message)
{
case WM_CLOSE:
{
PostMessageA(window, WM_QUIT, 0, 0);
} break;
//this should be handled by OBGGetEvent
case OBG_WM_RESIZE:
{
printf("MESSAGE WENT THROUGH. DON'T WANT THIS\n");
} break;
case WM_SIZE:
{
if (fInSizeLoop) // in modal size loop, defer notification
fResized = true;
else
PostMessageA(window, OBG_WM_RESIZE, wParam, lParam);
} break;
case WM_ENTERSIZEMOVE:
fInSizeLoop = true; // begin modal size loop
break;
case WM_EXITSIZEMOVE:
fInSizeLoop = false; // left modal size loop
// post resize notification now
if (fResized) {
RECT rc;
GetClientRect(window, &rc);
PostMessageA(window, OBG_WM_RESIZE, 0, MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top));
fResized = false;
}
break;
default:
{
result = DefWindowProc(window, message, wParam, lParam);
} break;
}
return result;
}
(sorry, this is C++ code and I just noticed you had tagged as C - but the principle is the same).

XI2. How to ignore events of modifier keys?

I'm trying to fix xneur keyboard switcher. Its author tried to add XI2 support, but broke input in the applications that use only XI2(google chrome for example).
And I'm stuck with modifiers filtering. There is the following code:
// Grab all keys...
if (has_x_input_extension) {
XIEventMask mask;
mask.deviceid = XIAllDevices;
mask.mask_len = XIMaskLen(XI_KeyPress)+
XIMaskLen(XI_KeyRelease);
mask.mask = (void *)calloc(mask.mask_len, sizeof(char));
XISetMask(mask.mask, XI_KeyPress);
XISetMask(mask.mask, XI_KeyRelease);
XISelectEvents(main_window->display, DefaultRootWindow(main_window->display), &mask, 1);
free(mask.mask);
}
else {
XGrabKey(main_window->display, AnyKey, AnyModifier, window, FALSE, GrabModeAsync, GrabModeAsync);
// ...without ModKeys.
grab_modifier_keys(window, FALSE);
}
grab_modifier_keys ungrabs key modifiers. And I don't know how to do the same with XI2(if branch).
I think it's possible to ignore those events in the event handling loop. Something like this:
int is_modifier (XEvent *event)
{
/* ??? */
}
while (1) {
XEvent event;
XNextEvent(display, &event);
if (is_modifier(event)) {
continue;
}
}
But I don't know how to implement is_modifier function.
I'd appreciate any help
Probably not a perfect solution, but here is an implementation of is_modifier I came up with:
Bool is_modifier(KeySym key_sym)
{
XModifierKeymap *modmap = XGetModifierMapping(main_window->display);
if (modmap == NULL) {
return False;
}
KeyCode key_code = XKeysymToKeycode(main_window->display, key_sym);
int size = modmap->max_keypermod * 8;
for (int i = 0; i < size; ++i) {
if (key_code == modmap->modifiermap[i]) {
return True;
}
}
XFreeModifiermap(modmap);
return False;
}

Windows 7 DLL Injection

I am trying to inject a dll into an existing process. I am trying to use the CreateRemoteThread LoadLibrary way. I understand how it works, but I cannot figure out why CreateRemoteThread is returning null (failing)... I am on Windows 7 so this may be the reason, but I don't know for sure if it is.. Perhaps I need to set privaleges? My code is below:
#define DLL_NAME "message.dll"
void main()
{
InjectDLL(1288, DLL_NAME);
}
BOOL InjectDLL(DWORD dwProcessId, LPCSTR lpszDLLPath)
{
HANDLE hProcess, hThread;
LPVOID lpBaseAddr, lpFuncAddr;
DWORD dwMemSize, dwExitCode;
BOOL bSuccess = FALSE;
HMODULE hUserDLL;
if((hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION
|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, dwProcessId)))
{
dwMemSize = lstrlen(lpszDLLPath) + 1;
if(lpBaseAddr = VirtualAllocEx(hProcess, NULL, dwMemSize, MEM_COMMIT, PAGE_READWRITE))
{
if(WriteProcessMemory(hProcess, lpBaseAddr, lpszDLLPath, dwMemSize, NULL))
{
if(hUserDLL = LoadLibrary(TEXT("kernel32.dll")))
{
if(lpFuncAddr = GetProcAddress(hUserDLL, TEXT("LoadLibraryA")))
{
if(hThread = CreateRemoteThread(hProcess, NULL, 0, lpFuncAddr, lpBaseAddr, 0, NULL))
{
WaitForSingleObject(hThread, INFINITE);
if(GetExitCodeThread(hThread, &dwExitCode)) {
bSuccess = (dwExitCode != 0) ? TRUE : FALSE;
}
CloseHandle(hThread);
}
}
FreeLibrary(hUserDLL);
}
}
VirtualFreeEx(hProcess, lpBaseAddr, 0, MEM_RELEASE);
}
CloseHandle(hProcess);
}
return bSuccess;
}
yes you need privileges before you open the precess, here's the code:
int GimmePrivileges(){
HANDLE Token;
TOKEN_PRIVILEGES tp;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token)
{
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid); tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(Token, 0, &tp, sizeof(tp), NULL, NULL);
}
}
An other thing... this code is confusing!!! you need to synthesize!

How to make window non transparent?

I want to make parent window as non transparent with RGB value as (99,99,99)? Previously my window was transparent but now i have requirement to make window as non transparent.
Mentioned below are the function related to my parent window:
ATOM MyRegisterClass(HINSTANCE hInstance)
{
LogEntry(L"Entered in myRegisterClass Function");
WNDCLASS CLASS_NAME_ONE_SEG_APP;
CLASS_NAME_ONE_SEG_APP.cbClsExtra = 0;
CLASS_NAME_ONE_SEG_APP.cbWndExtra = 0;
CLASS_NAME_ONE_SEG_APP.hbrBackground = 0;
CLASS_NAME_ONE_SEG_APP.hCursor = 0;
CLASS_NAME_ONE_SEG_APP.hIcon = 0;
CLASS_NAME_ONE_SEG_APP.hInstance = hInstance;
CLASS_NAME_ONE_SEG_APP.lpfnWndProc = (WNDPROC) WndProc;
CLASS_NAME_ONE_SEG_APP.lpszClassName = className;
CLASS_NAME_ONE_SEG_APP.lpszMenuName = 0;
CLASS_NAME_ONE_SEG_APP.style = 0;
LogEntry(L"Exiting from myRegisterClass Function");
return RegisterClass(&CLASS_NAME_ONE_SEG_APP);
}
Mentioned below is an InitInstance function in which i am creating the parent window.
handles.parent is my parent window.
bool WINAPI InitInstance(HINSTANCE hInstance, int nCmdShow)
{
LogEntry(L"Entered in InitInstance Function");
handles.parent = CreateWindowEx(0,
className,
windowName,
WS_VISIBLE | WS_POPUP,
0, 0,
coordinates.width, coordinates.height,
NULL,
NULL,
hInstance,
NULL);
if(handles.parent == NULL)
{
LogValue(L"Cannot Create Parent Window"
L"\nInitInstance Function terminated abnormally");
return false;
}
else
{
UpdateWindow(handles.parent);
ShowWindow(handles.parent, nCmdShow);
LogEntry(L"Exiting from InitInstance Function");
return true;
}
}
The below mentioned is a function for WM_PAINT:
case WM_PAINT:
LogEntry(L"Entred in WM_PAINT");
PaintWindow();
SetFocus(handles.parent);
LogEntry(L"Exited from WM_PAINT");
break;
This PaintWindow does the following.....
void PaintWindow()
{
LogEntry(L"Entered in PaintWindow Function");
HWND *handle = &handles.volUp;
//Paint Buttons on the window
for(register char i = MIN_BUTTON; i <= MAX_BUTTON; i++)
{
PaintButton( (INITIAL_BUTTON + i) , *handle, btns, i);
handle++;
}
//Paint the AXIS_VOL_ON_OFF Button According to its Status
if(volumeStatus.status == VOLUME_ON)
PaintButton(IDB_BTN_VOL_OFF, handles.volOnOff, btns, AXIS_VOL_ON_OFF);
else if(volumeStatus.status = VOLUME_MUTE)
PaintButton(IDB_BTN_VOL_ON, handles.volOnOff, btns, AXIS_VOL_ON_OFF);
//Paint Images on the window
if(handles.screenMode == SCREEN_MODE_OPERATION)
InsertImages();
LogEntry(L"Exited from PaintWindow Function");
}
Thanks in advance......
You need to give your class a non-null background brush
CLASS_NAME_ONE_SEG_APP.hbrBackground = CreateSolidBrush(RGB((99,99,99));
And in your WindowProc, you need to make sure that you pass the WM_ERASEBKGND message to DefWindowProc. (that part is probably already happening)
Later
Ok, your WM_PAINT code is doing some things wrong. It's important that you call BeginPaint and EndPaint when you handle the WM_PAINT message, and you have to use the HDC that you get from BeginPaint when you draw.
case WM_PAINT:
{
LogEntry(L"Entred in WM_PAINT");
PAINTSTRUCT ps;
HDC hdc = BeginPaint(&ps);
PaintWindow(hdc);
EndPaint(hwnd, &ps);
LogEntry(L"Exited from WM_PAINT");
}
break;
Your window is transparent because you never call BeginPaint in your WM_PAINT handler, so you never end up drawing anything to the screen.
See Drawing in the Client Area for a more complete example.

Resources