I am in a sticky situation.
I'm messing around with Bitmaps and windows.
I followed this tutorial: https://learn.microsoft.com/en-us/windows/win32/gdi/capturing-an-image
I am basically taking multiple pictures of my desktop and displaying them into a window.
It works great as intended but after like a minute or 2 the window won't update and I can't find the error or why this is occurring.
Here is the code:
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_DESTROY: {
PostQuitMessage(0); // Exit the program if the window gets closed.
} break;
case WM_SIZE: {
} break;
}
return DefWindowProc(hWnd, message, wParam, lParam); // Handle any messages the switch statement didn't
}
HWND SpawnWindow() {
WNDCLASSEX WindowClass;
SecureZeroMemory(&WindowClass, sizeof(WNDCLASSEX));
WindowClass.cbClsExtra = NULL;
WindowClass.cbWndExtra = NULL;
WindowClass.cbSize = sizeof(WNDCLASSEX);
WindowClass.style = CS_HREDRAW | CS_VREDRAW;
WindowClass.lpfnWndProc = WinProc;
WindowClass.hInstance = NULL;
WindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WindowClass.hIcon = LoadIcon(0, IDI_APPLICATION);
WindowClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
WindowClass.hbrBackground = NULL;
WindowClass.lpszClassName = L"Class NAme";
WindowClass.lpszMenuName = L"Menu Name";
RegisterClassEx(&WindowClass);
return CreateWindowEx(NULL, L"Class Name", L"Window Title", WS_VISIBLE | WS_TILEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);
}
void DoMessages() {
MSG msg = {};
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE | PM_NOYIELD)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
std::cout << msg.message << "\n";
}
int main() {
HWND WindowToGetPic = SpawnWindow();
HDC DesktopDC = GetDC(0);
HDC WindowDC = GetDC(WindowToGetPic);
if (!DesktopDC)
std::cout << "DC NULL!\n";
HDC TempDC = CreateCompatibleDC(DesktopDC);
HDC TempDCWindow = CreateCompatibleDC(WindowDC);
if (!TempDC)
std::cout << "TempDC NULL!\n";
while (true) {
/*
after calling CreateCompatibleDC you mus then call CreateCompatiableBitmap with the DC recieved
then call SelectObject
*/
HBITMAP hBitmap = CreateCompatibleBitmap(TempDC, 1920, 1080);/* screen res */
SelectObject(TempDC, hBitmap);
SetStretchBltMode(TempDC, HALFTONE);
RECT WindowDimensions;
GetClientRect(WindowToGetPic, &WindowDimensions);
if (!BitBlt(WindowDC, 0, 0, WindowDimensions.right - WindowDimensions.left, WindowDimensions.bottom - WindowDimensions.top, DesktopDC, 0, 0, SRCCOPY))
std::cout << "BitBlt ERROR\n";
DoMessages();
InvalidateRect(WindowHwnd, NULL, TRUE);
}
std::cin.ignore();
return 0;
}
If anyone could test this, or spot why the window doesn't update after a minute or two I would really appreciate it.
Thank you in advance!
I think you have spent all resources.
For example,
You create bitmap every cycle and don't release it.
You call SelectObject and don't return selected object to original state.
You have several resource leaks:
when you are done with an HDC returned by GetDC, call ReleaseDC
when you are done with an HDC returned by CreateCompatibleDC, call DeleteDC
when you are done with hBitmap, select the original bitmap back into the DC and call DeleteObject. The original bitmap is returned by SelectObject.
This is all covered in the documentation (Google will find it).
Related
How to make drag & drop? On the win32 machine it works without problems but on the x64 the WM_DROPFILES message is not called at all. Where is the problem?
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_CREATE: {
SetTimer(hWnd, 0, int(1000./24), NULL);
DragAcceptFiles(hWnd, true);
return 0;
}
case WM_DROPFILES: {
DEBUG;
return 0;
}
case WM_DESTROY:
KillTimer(hWnd, 0);
PostQuitMessage(0);
break;
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
HWND hWnd; WNDCLASSEX wCs;
static const char* wndClassName = "WndClass";
wCs.cbSize = sizeof wCs;
wCs.style = CS_HREDRAW | CS_VREDRAW;
wCs.lpfnWndProc = WindowProc;
wCs.cbClsExtra = 0;
wCs.cbWndExtra = 0;
wCs.hInstance = hInstance;
wCs.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ID_MYICON));
wCs.hCursor = LoadCursor(NULL, IDC_ARROW);
wCs.hbrBackground = NULL;
wCs.lpszMenuName = NULL;
wCs.lpszClassName = wndClassName;
wCs.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(ID_MYICON));
if (RegisterClassEx(&wCs)) {
hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE | WS_EX_ACCEPTFILES, // extended window style
wndClassName, // registered class name
TEXT("APP"), // and window title
WS_OVERLAPPEDWINDOW, // window style
CW_USEDEFAULT, CW_USEDEFAULT, g_winw, g_winh,
NULL, NULL, hInstance, // handle to application instance
this // if need to take pointer
);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM)this);
}
if(hWnd==NULL) {
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return E_FAIL;
}
if (s_winstate==3)
ShowWindow(hWnd, SW_MAXIMIZE);
else
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
mHInstance=hInstance;
hfont = CreateFont(15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Arial");
SendMessage(hWnd, WM_SETFONT, (WPARAM)hfont, TRUE);
I found in another topic from here that drag & drop would be problems with x64 Drag-and-drop from 32 to 64-bit
The difference is that the WM_DROPFILES message doesn't appear to me at all
Adding
ChangeWindowMessageFilter (WM_DROPFILES, MSGFLT_ADD);
ChangeWindowMessageFilter (WM_COPYDATA, MSGFLT_ADD);
ChangeWindowMessageFilter (0x0049, MSGFLT_ADD);
After SendMessage(hWnd, WM_SETFONT, (WPARAM)hfont, TRUE); solve the problem - thanks.
I am currently making a small win32 window wrapper class, but I have a few problem.
If I hit the close(X) button of the window the window closes immediately without sending a quit or destroy message, so I can't for example prevent the window to close or save something before closing the window.
And the second problem/question is,
If I use this small code to use the window, the computer cpu gets strongly used.
But its only a small window.
How I can change/fix this?
int main()
{
glwCreate();
while(true/*Later here comes a method that checks, wether window close is requested*/)
{
glwUpdate();
}
glwDestroy();
return 0;
}
-
#include "glw.h"
#include <windows.h>
#include <iostream>
HINSTANCE instanceHandle;
WNDCLASSEX windowClass;
HWND windowHandle;
LRESULT CALLBACK WindowMessageHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
std::cout<<uMsg<<'\n';
switch(uMsg)
{
case WM_QUIT:
{
std::cout<<"QUIT\n";
return 0;
}
case WM_DESTROY:
{
std::cout<<"DESTROY\n";
return 0;
}
}
return (DefWindowProc(hWnd, uMsg, wParam, lParam));
}
void glwCreate()
{
instanceHandle = GetModuleHandle(0);
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = WindowMessageHandler;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = instanceHandle;
windowClass.hCursor = LoadCursor(0,IDC_ARROW);
windowClass.hIcon = LoadIcon(0, IDI_APPLICATION);
windowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
windowClass.lpszClassName = "atomus_window_class";
windowClass.lpszMenuName = "menu_name";
windowClass.hIconSm = LoadIcon(0, IDI_APPLICATION);
RegisterClassEx(&windowClass);
windowHandle = CreateWindowEx( 0,
"atomus_window_class",
"atomus title",
WS_OVERLAPPEDWINDOW,
0,
0,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
instanceHandle,
0);
ShowWindow(windowHandle, SW_SHOW);
}
void glwDestroy()
{
DestroyWindow(windowHandle);
windowHandle = 0;
UnregisterClass(windowClass.lpszClassName, instanceHandle);
}
void glwUpdate()
{
MSG message;
while (PeekMessage (&message, 0, 0, 0, PM_REMOVE) > 0) //Or use an if statement
{
TranslateMessage (&message);
DispatchMessage (&message);
}
}
If you add handling for WM_CLOSE you get to control whether your window closes or not. By not providing your own handling for that message you get the default from DefWindowProc which is to destroy your window.
I need some help here.
Im importing an bitmap onto my Win32 Window. I am building it and after some seconds it's starting to lag a lot. I am not sure why, but I suppose I am not correctly deleting it from memory after using it.
Thank you for Help in advance.
I saw a behavior while I was testing it. If Im not moving the window than it is okey, but after moving it it start to lag and block my IDE. Maybe something with WM_PAINT?
Here is my code.
#include <windows.h>
//For more makros
#include <windowsx.h>
#include "Simulatron.h"
HINSTANCE hProgramInstance;
Simulatron Exo;
char Simulatron::m_szClassName[] = "Simulatron";
Simulatron::Simulatron(HINSTANCE hInstance)
{
m_hInstance = hInstance; // Save Instance handle
m_wndClass.cbSize = sizeof(WNDCLASSEX); // Must always be sizeof(WNDCLASSEX)
m_wndClass.style = CS_DBLCLKS; // Class styles
m_wndClass.lpfnWndProc = MainWndProc; // Pointer to callback procedure
m_wndClass.cbClsExtra = 0; // Extra bytes to allocate following the wndclassex structure
m_wndClass.cbWndExtra = 0; // Extra bytes to allocate following an instance of the structure
m_wndClass.hInstance = hInstance; // Instance of the application
m_wndClass.hIcon = NULL;//LoadIcon(hInstance, MAKEINTRESOURCE(IDC_MAINCURSOR)); // Class Icon
m_wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // Class cursor
m_wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // Background brush
m_wndClass.lpszMenuName = NULL; // Menu Resource
m_wndClass.lpszClassName = (LPCWSTR)m_szClassName; // Name of this class
m_wndClass.hIconSm = NULL;//LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); // Small icon for this class
}
Simulatron::~Simulatron()
{
}
Simulatron::Simulatron()
{
// If we declare a window class with a default constructor,
// we need to reset the window to a nothing
}
LRESULT CALLBACK Simulatron::MainWndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static HDC hdc;
static PAINTSTRUCT ps;
static HDC hdc_mem;
static HBRUSH newbrush;
//Child Window Handles
Simulatron create;
RECT rect;
hProgramInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
static HBITMAP logo = NULL;
static BITMAP bitmap;
logo = (HBITMAP)LoadImage(hProgramInstance, L"Space.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(logo, sizeof(bitmap), &bitmap);
switch (msg)
{
case WM_CREATE:
{
create.Create(hProgramInstance,hwnd,lParam,logo);
}
break;
case WM_GETMINMAXINFO:
{
LPMINMAXINFO pInfo = (LPMINMAXINFO) lParam;
//pInfo -> ptMaxTrackSize.x = 450;
//pInfo -> ptMaxTrackSize.y = 650;
}
break;
case WM_SIZE:
break;
case WM_CTLCOLORSTATIC:
SetTextColor((HDC)wParam, RGB(150, 100, 255));
SetBkMode((HDC)wParam, TRANSPARENT);
newbrush = (HBRUSH)GetStockObject(NULL_BRUSH);
DeleteObject(newbrush);
return (LRESULT)newbrush;
break;
case WM_COMMAND:
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd , &rect);
hdc_mem = CreateCompatibleDC(hdc);
SelectObject(hdc_mem, logo);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdc_mem, 0, 0, SRCCOPY);
DeleteObject(hdc_mem);
EndPaint(hwnd, &ps);
break;
//Handle the combinations from the keyboard input
case WM_DESTROY:
PostQuitMessage (0);
DeleteObject(logo);
DeleteBitmap(logo);
break;
default:
return DefWindowProc (hwnd, msg, wParam, lParam);
}
return 0;
}
//Create function of all Childs
void Simulatron::Create(HINSTANCE Hinst, HWND hWindow, LPARAM lParam, HBITMAP logo)
{
Hinst = ((LPCREATESTRUCT) lParam) -> hInstance; // handle to instance for custom cursor
logo = (HBITMAP)LoadImage(Hinst, L"Space.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
bool Simulatron::Run(int nCmdShow)
{
if(!RegisterClassEx(&m_wndClass))
return false;
m_hwnd = CreateWindowEx(0,(LPCWSTR)m_szClassName,
L"Simulatron",
//WS_OVERLAPPEDWINDOW,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, // Dissable Resizing and Maximizing
0, 0, 1280, 1000,
NULL, NULL,
m_hInstance,
NULL);
if(!m_hwnd)
return false;
ShowWindow(m_hwnd, nCmdShow);
return true;
}
Simulatron::operator HWND()
{
// This overloaded operator allows us to use HWND anyway we want
return m_hwnd;
}
You load the BMP File over and over again in your MainWndProc. You should load it once at Init and use it from there! Have a look at a win32 API tutorial and you will see that MainWndProc is getting called throughout the whole program lifetime. You could load that image in your WM_CREATE state for example.
I have tried this:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_SIZE:
case WM_MOVE:
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
return 0;
}
case WM_CTLCOLORSTATIC:
{
HDC hdc = (HDC) wParam;
SetBkMode (hdc, TRANSPARENT);
return (LRESULT)(GetStockObject(NULL_BRUSH));
}
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int main()
{
WNDCLASSEX wc;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = NULL;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)(GetStockObject(NULL_BRUSH));
wc.lpszMenuName = NULL;
wc.lpszClassName = L"MY CLASS";
wc.hIconSm = NULL;
RegisterClassEx(&wc);
HWND hwnd = CreateWindowEx(0, L"MY CLASS", NULL, WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, NULL, NULL);
HWND child = CreateWindowEx(0, L"STATIC", L"Text", WS_VISIBLE | WS_CHILD , 50, 50, 50, 50, hwnd, NULL, NULL, NULL);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}
It creates window, which looks transparent, because it shows the same as on screen, however after moving window main window background stays the same. I want to ask, where the problem may be.
P.S. it is just test code, so, please, do not write advices not suited with my question.
Thanks.
EDIT: I want this because I'm going to make some helpers for users who don't know how to do some stuff. Result should be something like regular some program view with come spots marked, what means press here, when here, after that here and etc.
I think you start point should be with taking a look on Layered Windows
http://msdn.microsoft.com/en-us/library/ms997507.aspx
it is most common way for playing with custom shape and (semi)transparent windows.
UPD. There is also old API for making custom shaped windows:
int SetWindowRgn( HWND hWnd, HRGN hRgn, BOOL bRedraw );
Look At this code and please tell me why when I compile it I see a blank white screen:
#include <windows.h>
#include <fstream.h>
#include <stdlib.h>
static char g_szClassName[] = "TEST";
static HINSTANCE g_hInst = NULL;
int savenumber = 1;
char savestring[] = "abc";
HWND hwnd;
HDC hdcWindow;
PAINTSTRUCT ps;
RECT rc;
//HBITMAP mario1,mario2,mario3,mario4,mario5,mario6,
// block1,block2,block3,scene1,scene1mask;
HBITMAP scene1;
BITMAP bm;
LRESULT CALLBACK
WndProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
HBITMAP g_hbitmap = NULL;
switch(nMsg)
{
case WM_CREATE:
g_hbitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL),
"C:\\Users\\Onwer\\Desktop\\Cpp code Initiate\\Jacob GRAPIC#3 cpp renewal!\\G3-Images\\scene.bmp",
IMAGE_BITMAP,
640,
320,
LR_LOADFROMFILE);
/*
mario1 = LoadBitmap(g_hInst, "MARIO1BMP");
mario2 = LoadBitmap(g_hInst, "MARIO2BMP");
mario3 = LoadBitmap(g_hInst, "MARIO3BMP");
mario4 = LoadBitmap(g_hInst, "MARIO4BMP");
mario5 = LoadBitmap(g_hInst, "MARIO5BMP");
mario6 = LoadBitmap(g_hInst, "MARIO6BMP");
block1 = LoadBitmap(g_hInst, "BLOCK1BMP");
block2 = LoadBitmap(g_hInst, "BLCOK2BMP");
block3 = LoadBitmap(g_hInst, "BLOCK3BMP");
scene1 = LoadBitmap(g_hInst, "SCENE1BMP");
scene1mask = LoadBitmap(g_hInst, "SCENE1MASKBMP");
*/
scene1 = LoadBitmap(g_hInst, "SCENE1BMP");
break;
case WM_TIMER:
break;
case WM_PAINT:
hdcWindow = BeginPaint(hwnd, &ps);
GetClientRect (hwnd, &rc);
drawScene (hdcWindow);
//DrawText(hdcWindow,"This Is a Test!", -1, &rc,
//DT_SINGLELINE | DT_TOP | DT_TOP );
EndPaint(hwnd, &ps);
break;
case WM_COMMAND:
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
/*
DeleteObject(mario1);
DeleteObject(mario2);
DeleteObject(mario3);
DeleteObject(mario4);
DeleteObject(mario5);
DeleteObject(mario6);
DeleteObject(block1);
DeleteObject(block2);
DeleteObject(block3);
*/
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, nMsg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
ofstream SaveFile ("save.txt");
SaveFile << savenumber << '\n' << savestring;
WNDCLASSEX WndClass;
HWND hwndMain;
MSG Msg;
g_hInst = hInstance;
WndClass.cbSize = sizeof(WNDCLASSEX);
WndClass.style = 0;
WndClass.lpfnWndProc = WndProc;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = g_hInst;
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = g_szClassName;
WndClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&WndClass))
{
MessageBox(0, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"TEST",
WS_OVERLAPPEDWINDOW,
//CW_USEDEFAULT, CW_USEDEFAULT, 677, 358,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 500,
NULL, NULL, g_hInst, NULL);
if(hwnd == NULL)
{
MessageBox(0, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK | MB_SYSTEMMODAL);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
I need to know why LoadImage doesn't display the picture designated. Is it not even supposed to? And if its not supposed t: tell me what function that goes with loadImage I should use, that is part of Windows.h in C++. I am using the Dev-C++ compiler.
All LoadImage does it loads an image, nothing else. If you want your application to draw an image in a window you have to do it yourself.
The contents of drawScene() were commented out (since removed in an edit) and your WM_PAINT handler doesn't perform any drawing operations. If your bitmap was successfully loaded you will need to do something like below when you handle the WM_PAINT message.
hdcMemory = CreateCompatibleDC(hdcWindow);
HGDIOBJ oldBitmap = SelectObject(hdcMemory, g_hbitmap);
BitBlt(hdcWindow, 0, 0, 640, 320, hdcMemory, 0, 0, SRCCOPY);
SelectObject(hdcMemory, oldBitmap);
DeleteDC(hdcMemory);