My first WinAPI program in Qt Creator doesn't show window? - winapi

I am a newbie when it comes to using WinAPI. I am following a tutorial where I found a code snippet. The snippet demonstrates a basic program. I am posting my full code below:
#include "a.h"
#include "windows.h"
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX WndClsEx;
WndClsEx.cbSize = sizeof(WNDCLASSEX);
WndClsEx.style = CS_HREDRAW | CS_VREDRAW;
WndClsEx.lpfnWndProc = WndProcedure;
WndClsEx.cbClsExtra = 0;
WndClsEx.cbWndExtra = 0;
WndClsEx.hInstance = hInstance;
return 0;
}
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch(Msg)
{
case WM_DESTROY:
PostQuitMessage(WM_QUIT);
break;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
I don't get any error while running the code from Qt Creator. However, when running it no windows appear but the output console shows:
"MyProgram.exe exited with code 0"
What might cause this?

I am posting my full code below:
Your code looks a lot like standard Win32 but it is missing a lot of code.
For example this very simple test.cpp file contains a full working Win32 application:
#define STRICT
#include <windows.h>
long PASCAL WndProc (HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdParam, int nCmdShow)
{
static char szClassName[] = "Hello World";
MSG msg;
WNDCLASS wndclass;
memset(&wndclass, '\0', sizeof(wndclass));
wndclass.style = CS_HREDRAW|CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);
wndclass.lpszMenuName = 0;
wndclass.lpszClassName = szClassName;
RegisterClass (&wndclass);
// create a new window
HWND hwnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
szClassName,
"My Hello World Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow (hwnd, nCmdShow);
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
long APIENTRY WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_DESTROY:
PostQuitMessage (0);
return 0;
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
It can be compiled and linked from the command line:
C:\TEMP>cl test.cpp user32.lib gdi32.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
test.cpp
Microsoft (R) Incremental Linker Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
/out:test.exe
test.obj
user32.lib
gdi32.lib
The resulting test.exe can be run and it will display a window:
C:\TEMP>test.exe

As Hans Passant suggests in his comment, you're missing a lot of code. I don't know from which tutorial you copied this snippet, but surely there must be more code there.
For example, you have not registered it, nor created the actual window, you're not showing it and (as #rodrigo mentioned) you're missing the message loop. This example on MSDN illustrates what that all would look like.
And yes, you can perfectly develop applications in Qt Creator without actually using Qt for your user interface. I would however not dismiss it. Since you have all the tools at your disposal, have a look at Qt itself as well. You might just like it.

Related

Is there a way to detect if a Window has been flashed?

Using functions FlashWindow and FlashWindowEx, one can cause a window to flash. However, I can't seem to find any API that would detect if a window has been flashed. Does one exist?
Edit
Given that FLASHWINFO has DWORD dwFlags, I would have guessed that this info would be stored in the window and would be accessible using either GetWindowLongW or GetWindowLongPtrW, but I can't find it there.
Reason I need this is for automation.
According to the ShellProc:
lParam [in]
Type: LPARAM
HSHELL_REDRAW The value is TRUE if the window is flashing, or FALSE otherwise.
So we just need to add a SetWindowsHookExA function to catch the WH_SHELL message.
Here is a sample:
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK procShell(int, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
HHOOK hook = SetWindowsHookEx(WH_SHELL, procShell, NULL,GetCurrentThreadId());
int e = GetLastError();
static TCHAR szAppName[] = TEXT("Test Flashing");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
}
hwnd = CreateWindow(szAppName,
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
UnhookWindowsHookEx(hook);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_LBUTTONDOWN:
FlashWindow(hwnd, TRUE);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
LRESULT CALLBACK procShell(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode == HSHELL_REDRAW) {
if (lParam)
{
OutputDebugString(L"Window is flashing\n");
}
}
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
If we press the left button, the FlashWindow will be called. Then the hook function will get the HSHELL_REDRAW message and output:

How to handle the message-only window to get the messages from the console window?

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.

Linking WSAAsyncSelect with Mingw - undefined reference

I am porting a voip application I wrote in Borland to Mingw so I know the code works. I use the command line gcc -lws2_32 -mwindows voipapp.c -o voipapp and keep getting the error message
undefined reference to 'WSAAsyncSelect#16'".
It appears to be properly locating libws2_32.a since no error messages come up telling me otherwise. Any ideas as to what can be wrong? I have one of the most recent versions of mingw installed. Thanks!
My code is as follows:
#include <windows.h>
#include <winsock2.h>
#define __MT__
#include <mmreg.h>
#include <time.h>
#include <math.h>
#include <stdio.h>
#include <process.h>
#define WM_SOCKETREAD (WM_USER + 1)
SOCKET ListenSocket;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR szCmdLine, int iCmdShow) {
static char szAppName[] = "voip";
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof(wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszClassName = szAppName;
wndclass.lpszMenuName = NULL;
RegisterClassEx(&wndclass);
hwnd = CreateWindow(szAppName, "VOIP prototype",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
WSAAsyncSelect(ListenSocket, hwnd, WM_SOCKETREAD, FD_READ|FD_CLOSE);
while ( GetMessage(&msg, NULL, 0, 0) ) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
You must specify correct linking order.
Try:
gcc voipapp.c -o voipapp -mwindows -lws2_32

Programming Windows Compiler Link Error - unresolved external

I am new to Windows Programming.
I created a win32 console project (without preCompiled header) with VS2005. And the code as below.
// HelloWin.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include "stdafx.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int _tmain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HelloWin");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if(!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This Program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, // window class name
TEXT("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, // initial x position
CW_USEDEFAULT, // initial y position
CW_USEDEFAULT, // initial x size
CW_USEDEFAULT, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
switch(message)
{
case WM_CREATE:
PlaySound(TEXT("hellowin.wav"), NULL, SND_FILENAME | SND_ASYNC);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
DrawText(hdc, TEXT("Hello Windows XP"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
And now there is two Link Errors as this, Could anybody help me to fix this errors.
Does it caused by there is no hellowin.wav file in my local harddisk? If it does. What directory can I place a simular WAV file to?
Thanks.
1>Linking... 1>HelloWin.obj :
error LNK2019: unresolved external
symbol imp__PlaySoundW#12 referenced in function "long __stdcall
WndProc(struct HWND *,unsigned int,unsigned int,long)"
(?WndProc##YGJPAUHWND__##IIJ#Z)
1>D:\learning\windows\ProgrammingWindows(5thEdition)\HelloWin\Debug\HelloWin.exe
:
fatal error LNK1120: 1 unresolved externals 1>Build log was saved at
"file://d:\learning\windows\ProgrammingWindows(5thEdition)\HelloWin\HelloWin\Debug\BuildLog> .htm"
1>HelloWin - 2 error(s), 1 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
You have several problems here. Firstly you say that your application is a console app. If it is, then you are using the wrong main. Your subsystem is probably WINDOWS in which case your main should be this instead:
int CALLBACK _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdLine, int iCmdShow)
You also say you're not using precompiled headers but you have an include for stdafx.h. Your problems can be fixed by changing your main and also changing your includes to look like this:
#include <windows.h>
#include <tchar.h>
#pragma comment(lib, "Winmm.lib")
This allows the linker to look for the library file we tell it to. I also got rid of your precompiled header and replaced it with tchar.h since that is your only other dependency so far.
The fact hellowin.wav is not present at compilation time is irrelevant. The program only looks for it at runtime.

After calling MoveWindow() with TRUE, the window client area is still invalid

MSDN doc's for MoveWindow() says:
"If the bRepaint parameter is TRUE, the system sends the WM_PAINT message to the window procedure immediately after moving the window (that is, the MoveWindow function calls the UpdateWindow function)."
But when I call GetUpdateRect() after MoveWindow(), while processing the WM_LBUTTONDOWN message in the parent, I get a beep, which shows that the child is invalid. What is the explanation ???
#include <windows.h>
#include <windowsx.h>
#include <tchar.h>
HINSTANCE ghInstance;
LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, UINT wParam, LONG lParam);
LRESULT CALLBACK ChildProc (HWND hwnd, UINT message, UINT wParam, LONG lParam);
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASSEX wndclassx;
ghInstance = hInstance;
wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = 0;
wndclassx.lpfnWndProc = WindowProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = 0;
wndclassx.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclassx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclassx.lpszMenuName = NULL;
wndclassx.lpszClassName = _T("ParentWindow");
wndclassx.hIconSm = NULL;
if( !RegisterClassEx(&wndclassx) ) return 0;
wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = 0;
wndclassx.lpfnWndProc = ChildProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = 0;
wndclassx.hCursor = 0;
wndclassx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclassx.lpszMenuName = NULL;
wndclassx.lpszClassName = _T("ChildWindow");
wndclassx.hIconSm = NULL;
if( !RegisterClassEx(&wndclassx) ) return 0;
if( !(hWnd = CreateWindow(_T("ParentWindow"), _T("Parent Window"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance,
NULL)) ) return 0;
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
while( GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WindowProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
HWND hWnd;
switch ( message )
{
case WM_CREATE:
CreateWindow(_T("ChildWindow"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER, 10, 10, 100, 100, hwnd, (HMENU)0,
ghInstance, NULL);
break;
case WM_LBUTTONDOWN:
hWnd = GetWindow(hwnd, GW_CHILD);
MoveWindow(hWnd, 10, 10, 200, 200, true);
if( GetUpdateRect(hWnd, NULL, FALSE) ) MessageBeep(-1);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK ChildProc (HWND hwnd, UINT message, UINT wParam, LONG lParam)
{
return DefWindowProc(hwnd, message, wParam, lParam);
}
The MSDN doc's is wrong. MoveWindow() with TRUE doesn't call UpdateWindow() as the documentation says. It just invalidates the window client area. If I call UpdateWindow() just after MoveWindow() the program runs as expected.
I tried it myself and WM_PAINT is triggered before the if(GetUpdateRect()) is. Also, GetUpdateRect returns FALSE for me.
I'm running Visual Studio 2008 on XP.
I guess it could depend on what compiler you are using, what operating system that is used and whatnot. According to the code you passed everything is done in the same thread, but if it is a multithreaded program I think that this could inflict some issues as well.

Resources