I was trying to show a window using ShowWindow in a Callback function that called is set by a SetTime after I have hided it, but it didn't worked.
Please check the following code example.
#define _WIN32_WINNT 0x0500
#include<windows.h>
void CALLBACK f(HWND hwnd, UINT uMsg, UINT timerId, DWORD dwTime)
{
MessageBoxA(NULL,"Test","test2",MB_OK);
ShowWindow( hwnd, SW_SHOW ); //This will not show the window :(
MessageBoxA(NULL,"Is it shown?","test2",MB_OK);
}
int main()
{
MSG msg;
ShowWindow( GetConsoleWindow(), SW_HIDE );
SetTimer(NULL, 0, 1000*3, &f);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Thank you.
As #IInspectable suggested, it is the wrong handle that the call back function carries (which is the handle NULL which have been passed to SetTimer).
To correct the code above, you should use the same handle for both show and hide.
#define _WIN32_WINNT 0x0500
#include<windows.h>
HWND hwnd;
void CALLBACK f(HWND __hwnd__, UINT uMsg, UINT timerId, DWORD dwTime)
{
MessageBoxA(NULL,"Test","test2",MB_OK);
ShowWindow( hwnd, SW_SHOW ); //This will not show the window :(
MessageBoxA(NULL,"Is it shown?","test2",MB_OK);
}
int main()
{
MSG msg;
hwnd=GetConsoleWindow();
ShowWindow(hwnd , SW_HIDE );
SetTimer(NULL, 0, 1000*3, &f);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Thank you.
Related
I am hooking the keys and writing them down to a file, everything works fine but when I make the console window hidden, I can not hook the keys and print to a file, how to get rid of this problem? Down below when I removed ShowWindow() function I am able to hook the keys but otherwise I am not. I see the process is still running on task manager by the way.
See my example code here:
KBDLLHOOKSTRUCT kbdSTRUCT;
int APIENTRY WinMain(HINSTANCE hinstance, HINSTANCE hprevious, LPSTR cmdline, int cmdshow ) {
HWND wnd;
wnd = GetConsoleWindow();
ShowWindow(wnd, FALSE);
HHOOK kbdHOOK;
kbdHOOK = SetWindowsHookEx(WH_KEYBOARD_LL, kbdProc, NULL, 0);
MSG msgg;
while(GetMessage(&msgg, NULL, 0, 0) > 0){
TranslateMessage(&msgg);
DispatchMessage(&msgg);
}
}
LRESULT CALLBACK kbdProc(int nCode, WPARAM wPar, LPARAM lPar){
if(nCode >= 0){
if(wPar == 256){
kbdSTRUCT = *(KBDLLHOOKSTRUCT *)lPar;
if(kbdSTRUCT.vkCode == 0x90){
//fprintf function here to write to a file
return CallNextHookEx(NULL, nCode, wPar, lPar);
}
}
}
}
Thank you so much
When using gcc, -mwindows will set the Windows subsystem, this way no console window will appear when entry point is WinMain
gcc myfile.c -mwindows -o myfile.exe
Use a global variable to store SetWindowsHookEx result and pass it kbdProc, use that in CallNextHookEx
#include <Windows.h>
#include <stdio.h>
HHOOK hhook = NULL;
LRESULT CALLBACK kbdProc(int nCode, WPARAM wPar, LPARAM lPar)
{
if(nCode >= 0) {
if(wPar == WM_KEYDOWN) { //or WM_KEYUP!
KBDLLHOOKSTRUCT *kb = (KBDLLHOOKSTRUCT*)lPar;
int c = kb->vkCode;
FILE *file = fopen("test", "a");
switch(c) {
case VK_NUMLOCK: fprintf(file, "VK_NUMLOCK\n"); break;
case VK_RETURN: fprintf(file, "\n"); break;
default: fprintf(file, "%c", c); break;
}
fclose(file);
}
}
return CallNextHookEx(hhook, nCode, wPar, lPar);
}
int APIENTRY WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int show)
{
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, kbdProc, NULL, 0);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
UnhookWindowsHookEx(hhook);
return 0;
}
Make sure to use the correct windows constants. For example ShowWindow(wnd, SW_HIDE) instead of ShowWindow(wnd, FALSE). WM_KEYUP instead of 256. Otherwise the code will be too confusing when you look at the next day. Other people will not understand it.
You need to examine the shift key in addition to VK_NUMLOCK to find upper/lower case letters ...
The DATETIMEPICKERINFOstructure obtained by sending the DTM_GETDATETIMEPICKERINFOmessage has a field hwndEdit which might be what I'm looking for. However, I'm getting always NULL for it so I'm wondering what's its actual meaning. If not, is there a way to get the handle of the entry field?
hwndEdit only seems to be valid when the control has the DTS_APPCANPARSE style and you click the date text with the mouse (I tested this with OutputDebugString and a timer). The edit control is created and destroyed dynamically. The hwndUD handle is only valid if DTS_UPDOWN is set and the hwndDropDown is only valid while the dropdown is visible.
It is not called out in the documentation but DTM_GETDATETIMEPICKERINFO is marked Vista+ and this often means the feature is only implemented in ComCtl32 v6 so you also have to make sure you have a manifest that requests this version.
To change the color you can try DTM_SETMCCOLOR but only MCSC_BACKGROUND is documented to work when Visual Styles are active.
I'm afraid there is no way to get what you wanted. I just created a simple Win32 application just to test the possibility. If I use the DTM_GETDATETIMEPICKERINFO, hwndDropDown, hwndEdit and hwndUD give me NULL. If I try to enum child window, well before I do so I check it with Spy++, no luck, there is no child window associated with it.
Finally, I tried GetFocus() and WindowFromPoint(), both give me the HWND of the DateTimePicker itself only.
Here is my testing code:
#pragma comment(lib, "comctl32.lib")
#include <windows.h>
#include <tchar.h>
#include <commctrl.h>
enum MYID {
MYID_FIRST = WM_APP,
MYID_DTP
};
LPCTSTR const g_MyWndClass = _T("DTPTest");
LPCTSTR const g_MyWndTitle = _T("DTPTest");
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void OnWindowCreate(HWND);
void OnTimer(HWND);
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int nCmdShow)
{
INITCOMMONCONTROLSEX icex{};
icex.dwSize = sizeof(icex);
icex.dwICC = ICC_DATE_CLASSES;
InitCommonControlsEx(&icex);
WNDCLASSEX wcex{};
wcex.cbSize = sizeof(wcex);
wcex.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.lpfnWndProc = WndProc;
wcex.lpszClassName = g_MyWndClass;
wcex.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wcex);
HWND hwnd = CreateWindowEx(0,
g_MyWndClass, g_MyWndTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 600, 400,
nullptr, nullptr, nullptr, nullptr);
if (!hwnd) { return 99; }
SetTimer(hwnd, 0, 100, nullptr);
ShowWindow(hwnd, nCmdShow);
MSG msg{};
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l)
{
switch (msg) {
case WM_CREATE:
OnWindowCreate(hwnd);
break;
case WM_TIMER:
OnTimer(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, w, l);
}
return 0;
}
void OnWindowCreate(HWND hwnd)
{
HWND hwndDTP = CreateWindowEx(0, DATETIMEPICK_CLASS, nullptr,
WS_CHILD | WS_VISIBLE | DTS_SHOWNONE,
20, 50, 220, 20,
hwnd, reinterpret_cast<HMENU>(MYID_DTP), nullptr, nullptr);
DATETIMEPICKERINFO info{};
info.cbSize = sizeof(DATETIMEPICKERINFO);
SendMessage(hwndDTP, DTM_GETDATETIMEPICKERINFO, 0,
reinterpret_cast<LPARAM>(&info));
if (!info.hwndDropDown && !info.hwndEdit && !info.hwndUD)
{
MessageBox(hwnd, _T("No luck with DTM_GETDATETIMEPICKERINFO"),
nullptr, MB_ICONERROR);
}
}
void OnTimer(HWND hwnd)
{
POINT pt{};
GetCursorPos(&pt);
HWND hwndPoint = WindowFromPoint(pt);
HWND hwndFocus = GetFocus();
TCHAR buf[99]{};
wsprintf(buf, _T("Pointing at %p, focusing %p"),
hwndPoint, hwndFocus);
SetWindowText(hwnd, buf);
}
I've starting watching the handmade hero videos and I'm trying to make a win32 window but the CreateWindowEx() function keeps failing.
I checked the error code and I get 1407.
Code is below.
Thanks in advance.
#include <Windows.h>
LRESULT CALLBACK WindowProcedure(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
LRESULT result;
switch (uMsg)
{
case WM_ACTIVATEAPP:
{
OutputDebugStringA("The window is now active");
break;
}
case WM_SIZE:
{
OutputDebugStringA("The window is now being resized");
break;
}
case WM_CREATE:
{
OutputDebugStringA("The window has been created");
break;
}
default:
{
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
break;
}
}
return result;
};
int CALLBACK WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
WNDCLASS GameWindow;
GameWindow.style = CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
GameWindow.lpfnWndProc = WindowProcedure;
GameWindow.hInstance = hInstance;
// HICON hIcon;
GameWindow.lpszClassName = "HandmadeHeroWindowClass";
RegisterClass(&GameWindow);
if (HWND GameWindowHandle = CreateWindowEx(
0,
GameWindow.lpszClassName,
"Handmade Hero",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
hInstance,
0
))
{
for (;;)
{
MSG message;
BOOL messageResult = GetMessage(&message, GameWindowHandle, 0, 0);
if (messageResult != 0)
{
DispatchMessage(&message);
}
else if (messageResult == 0)
{
break;
}
else
{
// ERROR
}
}
}
else
{
OutputDebugStringA("Couldn't create window");
}
DWORD error = GetLastError();
return 0;
};
Your window procedure returns an uninitialized variable in every path except for default:, this is undefined behavior and failure of window creation is entirely possible.
For WM_CREATE, the documentation says:
If an application processes this message, it should return zero to continue creation of the window.
As Michael noted in the comments, RegisterClass is failing. Same category of mistake, you're passing a WNDCLASS structure leaving most members uninitialized.
Thanks to Remy Lebeau for the answer, the problem was that my WNDCLASS had uninitialized values for all fields except those I changed, this caused the RegisterClass() to fail and consequently the CreateWindowEx() to fail.
I changed WNDCLASS declaration to this:
WNDCLASS GameWindow = {0};
Thanks to everyone who helped.
Here is my code. I'm trying to create an edit control. It's not showing, however. Can some take a look at my code and point out the errors please. I can't figure out where the error is. I feel It might have something to do with the parent child relationship.
#include <cstdlib>
#include <windows.h>
#define MAINWINDOW_CLASS_ID 140;
const char* MAINWINDOW_CLASS_NAME = "Main Window";
const char* TEXTAREA_CLASS_NAME = "EDIT";
using namespace std;
LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam);
/*
* Initialize the window class and register it.
*/
BOOL initInstance(HINSTANCE hInstance);
/*
* Create and show the window
*/
HWND initWindow(HINSTANCE hInstance);
HWND createTextArea(HWND hParent);
/*
*
*/
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevInstance, LPSTR lpCmdline, INT cmdlShow)
{
if (!initInstance(hInstance))
return 0;
HWND hwndMain = initWindow(hInstance);
ShowWindow(hwndMain, cmdlShow);
MSG msg = {} ;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
BOOL initInstance(HINSTANCE hInstance)
{
WNDCLASS wc = {};
wc.lpfnWndProc = WinProc;
wc.hInstance = hInstance,
wc.lpszClassName = MAINWINDOW_CLASS_NAME;
return RegisterClass(&wc);
}
HWND initWindow(HINSTANCE hInstance)
{
HWND hwndMain = CreateWindow(
MAINWINDOW_CLASS_NAME, // The class name
"Text Editor", // The window name
WS_OVERLAPPEDWINDOW,// The window style
CW_USEDEFAULT, // The x pos
CW_USEDEFAULT, // The y pos
CW_USEDEFAULT, // The width
CW_USEDEFAULT, // The height
(HWND) NULL, // Handle to parent
(HMENU) NULL, // Handle to the menu
hInstance, // Handle to the instance
NULL // Window creation data
);
if (!hwndMain) {
return NULL;
}
else {
return hwndMain;
}
}
LRESULT CALLBACK WinProc(HWND hwnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) {
HWND htextArea;
char sztestText[] = "I should be able to see this text.";
switch (uMsg) {
case WM_CREATE:
htextArea = createTextArea(hwnd);
SendMessage(htextArea, WM_SETTEXT, 0, (LPARAM) sztestText);
break;
case WM_PAINT:
break;
case WM_CLOSE:
break;
case WM_SIZE:
RECT rectMainWindow;
GetWindowRect(hwnd, &rectMainWindow);
INT x = rectMainWindow.right - rectMainWindow.left + 50;
INT y = rectMainWindow.bottom - rectMainWindow.top + 50;
MoveWindow(htextArea, 0, 0, x, y, TRUE);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
/*******************************************************************/
HWND createTextArea(HWND hParent) {
return CreateWindow(
TEXTAREA_CLASS_NAME, // Class control name
NULL, // Title
WS_CHILD | WS_VISIBLE | ES_MULTILINE, // Styles
0, 0, 0, 0, // Sizing and position
hParent,
(HMENU) MAKEINTRESOURCE(100),
(HINSTANCE) GetWindowLong(hParent, GWL_HINSTANCE),
NULL
);
}
You've defined htextArea as a local variable in WinProc and so every time your window procedure is called its value will be uninitialized. You should make it static or move it to global data outside the function.
(The actual problem is that when you get a WM_SIZE message, you've lost the handle to the edit control, and so its size remains as 0,0).
I'm trying to know when a console window has moved so I created a new message-only window to get the messages of the console but I don't know if it is working because the message is apparently never being received.
#define WINVER 0x0501
#include <windows.h>
#include <iostream>
WNDPROC glpfnConsoleWindow; // NEW
using namespace std;
LRESULT APIENTRY MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
cout<<"Window moved"<<endl;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
// NEW
return CallWindowProc(glpfnConsoleWindow, hwnd, uMsg, wParam, lParam);
//return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd;
MSG Msg;
const char lpcszClassName[] = "messageClass";
WNDCLASSEX WindowClassEx;
// == NEW
HWND consHwnd;
consHwnd = GetConsoleWindow();
glpfnConsoleWindow = (WNDPROC)SetWindowLong(consHwnd, GWL_WNDPROC, (LONG)MainWndProc);
// ==
ZeroMemory(&WindowClassEx, sizeof(WNDCLASSEX));
WindowClassEx.cbSize = sizeof(WNDCLASSEX);
WindowClassEx.lpfnWndProc = MainWndProc;
WindowClassEx.hInstance = hInstance;
WindowClassEx.lpszClassName = lpcszClassName;
if (RegisterClassEx(&WindowClassEx) != 0)
{
// Create a message-only window
hwnd = CreateWindowEx(0, lpcszClassName, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
if (hwnd != NULL)
cout<<"Window created"<<endl;
else
UnregisterClass(lpcszClassName, hInstance);
}
ShowWindow(hwnd,nCmdShow);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return (int)Msg.wParam;
}
Perhaps you should process WM_MOVE, which, according to the documentation, is sent after the window has been moved. WM_SIZE is sent when the size changes.
I think your problem is that the WM_MOVE and WM_SIZE messages are going to the console window rather than to your hidden window.
I suspect you'll have to call GetConsoleWindow to get the console window handle, and then call SetWindowLong to attach your window proc to the console window. Be sure to pass messages on to the original window proc.