How to display an image in a win32 application? - c++

I'm new to windows in c++ and i can't figure out how to display a image in my window?
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
//Display an image here.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
I have a .png file on my desktop with the file path of Desktop\Dirt.png. i want to display this on my window at the location of 0,0. I don't know how to do this so any help will be nice. Also a function for this would be helpful.

Related

GetWindowLong loses data of fields

I do a wrapper for Window and want to call window methods from WndProc.
For this I pass 'this' pointer to CreateWindwEx function.
In WndProc I assign hWnd field of Window class and store it by SetWindowLongPtr
But when I try to read it by GetWindowLong I get broken instance of the window (all the fields have undefined values), however I can call w->foo()
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_NCCREATE:
{
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
Window* self = static_cast<Window*>(lpcs->lpCreateParams);
// self->m_hInst and self->m_szWindowClass are set properly
// lets set hWnd
self->m_hWnd = hWnd;
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LPARAM>(self));
return true;
}
case WM_COMMAND:
{
Window* w = reinterpret_cast<Window*>(GetWindowLong(hWnd, GWLP_USERDATA));
// got all the windows fields broken, though 'w' pointer itself is valid
w->foo();
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
//DialogBox(m_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
Window* w = reinterpret_cast<Window*>(GetWindowLong(hWnd, GWLP_USERDATA));
w->foo();
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
void foo()
{
//auto d = m_hInst;
auto s = m_hWnd;
}
My fault!
GetWindowLongPtr should be used instead of GetWindowLong

Why doesn't drawing onto the hdc immediately update the window?

According to this website, any drawing operation performed on the HDC returned by BeginPaint will immediately display on the screen. However, the number printed by the following code only updates when the window is resized:
int counter = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
std::string s = std::to_string(counter).c_str();
TextOutA(hdc, 0, 0, s.c_str(), s.length());
EndPaint(hWnd, &ps);
}
break;
case WM_KEYDOWN:
counter++;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Even when continuously sending WM_PAINT to the window with
RedrawWindow(hwndMain, 0, 0, RDW_INTERNALPAINT);
after EndPaint, the number only updates when the window is resized. How can I get the number to update without manually resizing the window?
Calling RedrawWindow with different flags solved the problem.
Specifically RedrawWindow(hWnd, 0, 0, RDW_FRAME | RDW_INVALIDATE); after counter++;

SendMessage() and PostMessage() proper usage

I've got a problem with using SendMessage() and PostMessage() properly. The thing what i'm trying to do is SendMessage(hWnd, WM_USER + 1, 0, 0); in my window procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case WM_CREATE:
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case WM_USER:
break;
case WM_USER + 1:
break;
default:
if (grid.ProcessEvent(wmId, wmEvent))
{
SendMessage(hWnd, WM_USER + 1, 0, 0);
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Im not really sure why it doesn't work, maybe someone could help. I'm sure SendMessage(...) is called but it doesn't affect to run WndProc with my arguments.
The case label case WM_USER + 1: is nested in the inner case statement (that switches on wmId). It needs to be moved out to the switch (message) case statement, so it is at the same level of nesting as case WM_COMMAND: and case WM_DESTROY:.
The above also applies to case WM_USER:.
SendMessage is specified to not return until the receiver window has processed the message - which it cannot do as you're inside your own WndProc and messaging yourself. This is one of those cases where you should be using PostMessage.

C++ Windows Minimize Not Registered

I have added minimize & restore cases to my even processing, but I found out they are never hit.
Only on startup of the program does Size_Minimized get hit. Afterwards, minimize case never happens.
The Size_Restore case never happens either.
Debug stopping at Size_Minimize only on startup of program:
My other cases work, so I have no idea why minimize & restore dont trigger my code or break points.
I conclude that Size_Minimized & Size_Restore are not related to what I need.
What is it I need to know to handle minimize/restore?
Code, in case I did it wrong:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
PAINTSTRUCT ps;
HDC hdc;
switch(message){
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case SIZE_MINIMIZED:
break;
case SIZE_RESTORED:
break;
case WM_SIZING:
case WM_SIZE:
if(engine.isReady()) engine.resizeDevice();
if(engine.isReady()) engine.draw();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
SIZE_MINIMIZED and SIZE_RESTORED are constants passed to you through the WM_SIZE message; they are not window messages. Your breakpoint is getting hit whenever your window receives a window message with the same id as SIZE_MINIMIZED and/or SIZE_RESTORED.
You would need to have your code look something like this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
PAINTSTRUCT ps;
HDC hdc;
switch(message){
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_SIZE:
switch(wParam) {
case SIZE_MINIMIZED:
// Do whatever
break;
case SIZE_RESTORED:
// Do whatever
break;
}
case WM_SIZING:
if(engine.isReady()) engine.resizeDevice();
if(engine.isReady()) engine.draw();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

Disable keyboard keys when the console of c Run using c or c++

I want to disable keyboard when my program Run, means that no one can use alt+F4 etc. How I can make it possible using c in window OS.
Handle WM_SYSKEYUP , WM_SYSKEYDOWN and return 0
Here's the WndProc to handle these messages
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_KEYUP:
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Pressing alt + f4 sends WM_CLOSE message.
You should properly handled this message.