Getting Rid of Black Console Window When Running C++ Application - c++

I am using Netbeans 7.1 to toy around with the AI tutorial I found here.
edit: I am using the GCC compiler.
I've gotten everything working, but I can't seem to get the application to compile and run with the Windows Subsystem... The application appears to be written properly for Windows API, and the executable that came with the source files from that website launches without producing the black console window that my own executable creates.
I've tried adding -mwindows as an option to the linker, and I've tried -Wl,-subsystem,windows. Neither of these have worked for me. I've provided the main.cpp below.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <time.h>
#include "utils.h"
#include "CController.h"
#include "CTimer.h"
#include "resource.h"
#include "CParams.h"
// edited this out, still not working
// #pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
///////////////////////GLOBALS ////////////////////////////////////
char* szApplicationName = "Smart Sweepers v1.0";
char* szWindowClassName = "sweeper";
//The controller class for this simulation
CController* g_pController = NULL;
//create an instance of the parameter class.
CParams g_Params;
//---------------------------- Cleanup ----------------------------------
//
// simply cleans up any memory issues when the application exits
//-----------------------------------------------------------------------
void Cleanup()
{
if (g_pController)
delete g_pController;
}
//-----------------------------------WinProc-----------------------------
//
//-----------------------------------------------------------------------
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
//these hold the dimensions of the client window area
static int cxClient, cyClient;
//used to create the back buffer
static HDC hdcBackBuffer;
static HBITMAP hBitmap;
static HBITMAP hOldBitmap;
switch(msg)
{
case WM_CREATE:
{
//seed the random number generator
srand((unsigned) time(NULL));
//get the size of the client window
RECT rect;
GetClientRect(hwnd, &rect);
cxClient = rect.right;
cyClient = rect.bottom;
//setup the controller
g_pController = new CController(hwnd);
//create a surface for us to render to(backbuffer)
hdcBackBuffer = CreateCompatibleDC(NULL);
HDC hdc = GetDC(hwnd);
hBitmap = CreateCompatibleBitmap(hdc,
cxClient,
cyClient);
ReleaseDC(hwnd, hdc);
hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap);
}
break;
//check key press messages
case WM_KEYUP:
{
switch(wparam)
{
case VK_ESCAPE:
{
PostQuitMessage(0);
}
break;
case 'F':
{
g_pController->FastRenderToggle();
}
break;
//reset the demo
case 'R':
{
if (g_pController)
{
delete g_pController;
}
//setup the new controller
g_pController = new CController(hwnd);
}
break;
}//end WM_KEYUP switch
}
break;
//has the user resized the client area?
case WM_SIZE:
{
cxClient = LOWORD(lparam);
cyClient = HIWORD(lparam);
//resize the backbuffer accordingly
SelectObject(hdcBackBuffer, hOldBitmap);
HDC hdc = GetDC(hwnd);
hBitmap = CreateCompatibleBitmap(hdc,
cxClient,
cyClient);
ReleaseDC(hwnd, hdc);
hOldBitmap = (HBITMAP)SelectObject(hdcBackBuffer, hBitmap);
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
//fill our backbuffer with white
BitBlt(hdcBackBuffer,
0,
0,
cxClient,
cyClient,
NULL,
NULL,
NULL,
WHITENESS);
//render the mines and sweepers
g_pController->Render(hdcBackBuffer);
//now blit backbuffer to front
BitBlt(ps.hdc, 0, 0, cxClient, cyClient, hdcBackBuffer, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
{
SelectObject(hdcBackBuffer, hOldBitmap);
//clean up our backbuffer objects
DeleteDC(hdcBackBuffer);
DeleteObject(hBitmap);
// kill the application, this sends a WM_QUIT message
PostQuitMessage(0);
}
break;
default:break;
}//end switch
// default msg handler
return (DefWindowProc(hwnd, msg, wparam, lparam));
}//end WinProc
//-----------------------------------WinMain-----------------------------------------
// Entry point for our windows application
//-----------------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{
WNDCLASSEX winclass;
HWND hwnd;
MSG msg;
// first fill in the window class stucture
winclass.cbSize = sizeof(WNDCLASSEX);
winclass.style = CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON1));
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground= NULL;
winclass.lpszMenuName = NULL;
winclass.lpszClassName= szWindowClassName;
winclass.hIconSm = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON1));
// register the window class
if (!RegisterClassEx(&winclass))
{
MessageBox(NULL, "Error Registering Class!", "Error", 0);
return 0;
}
// create the window (one that cannot be resized)
if (!(hwnd = CreateWindowEx(NULL,
szWindowClassName,
szApplicationName,
WS_OVERLAPPED | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
GetSystemMetrics(SM_CXSCREEN)/2 - CParams::WindowWidth/2,
GetSystemMetrics(SM_CYSCREEN)/2 - CParams::WindowHeight/2,
CParams::WindowWidth,
CParams::WindowHeight,
NULL,
NULL,
hinstance,
NULL)))
{
MessageBox(NULL, "Error Creating Window!", "Error", 0);
return 0;
}
//Show the window
ShowWindow(hwnd, SW_SHOWDEFAULT );
UpdateWindow(hwnd);
//create a timer
CTimer timer(CParams::iFramesPerSecond);
//start the timer
timer.Start();
// Enter the message loop
bool bDone = FALSE;
while(!bDone)
{
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
{
//Stop loop if it's a quit message
bDone = TRUE;
}
else
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
if (timer.ReadyForNextFrame() || g_pController->FastRender())
{
if(!g_pController->Update())
{
//we have a problem, end app
bDone = TRUE;
}
//this will call WM_PAINT which will render our scene
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
}//end while
// Clean up everything and exit the app
Cleanup();
UnregisterClass( szWindowClassName, winclass.hInstance );
return 0;
} // end WinMain

This seems a bit strange, but windows subsystem application uses WinMainCRTStartup as entry point. So the following line looks inconsistent:
#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup")
It probably should be "/SUBSYSTEM:windows /ENTRY:WinMainCRTStartup" or "/SUBSYSTEM:console /ENTRY:mainCRTStartup"
On the other hand, I never trried to make a windows app with gcc. It may completely ignore this #pragma... Anyway, try to comment it out and see what happens. Generally compiler should be able to select the proper entry point without the compile time parameter anyway.

Related

C++ resizing issue

I have successfully opened a win32 window(without OpenGL context). Opening the window, then resizing it causes a lot of issues. How do we properly handle resizing inside the win32 api? I create a window with WS_OVERLAPPEDWINDOW and making the window resizable. Mainly, I attempt to handle the resizing with the WM_SIZE event handler.
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <gl/GL.h>
#include <gl/GLU.h>
#include <iostream>
using namespace std;
HINSTANCE hInstanceGlobal;
LRESULT CALLBACK wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
PAINTSTRUCT ps;
switch (message) {
default:
return DefWindowProcA(hWnd, message, wParam, lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0;
case WM_SIZE:
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;
case WM_KEYDOWN:
break;
case WM_SETCURSOR:
if (LOWORD(lParam) == HTCLIENT) {
SetCursor(LoadCursor(NULL, IDC_ARROW));
return TRUE;
}
break;
}
return DefWindowProcA(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd) {
#ifdef _DEBUG
AllocConsole();
//SetWindowPos(GetConsoleWindow(), 0, 1920, 200, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
AttachConsole(GetCurrentProcessId());
freopen("CON", "w", stdout);
#endif
hInstanceGlobal = hInstance;
const char* CLASSNAME = "APIOPENGL";
WNDCLASS cl = { };
cl.lpfnWndProc = wndproc;
cl.hCursor = LoadCursor(NULL, IDC_ARROW);
cl.hInstance = hInstance;
cl.lpszClassName = CLASSNAME;
RegisterClass(&cl);
HWND hWnd = CreateWindowEx(
WS_EX_APPWINDOW|WS_EX_CLIENTEDGE,
CLASSNAME,
"Opengl Window",
WS_OVERLAPPEDWINDOW |WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL
);
if (hWnd == NULL)
{
return 0;
}
ShowWindow(hWnd, nShowCmd);
MSG msg;
MessageBox(NULL, (char*)GetLastError(), "Hello", NULL);
bool bRet;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (GetKeyState(VK_RMENU) & 0x8000)
{
cout << "Pressed" << endl;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Check this out: Resize window with Win32 API
In your WM_PAINT handler, it's possible that your getting that strange result because you aren't calling the FillRect function.
case WM_PAINT:
PAINTSTRUCT ps;
HDC hdc = BeginPaint(m_hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 6));
EndPaint(m_hwnd, &ps);
The problem in the screenshot (black background) is because you have not set the hbrBackground member of the window class. According to the document:
When this member is NULL, an application must paint its own
background whenever it is requested to paint in its client area. To
determine whether the background must be painted, an application can
either process the WM_ERASEBKGND message or test the fErase
member of the PAINTSTRUCT structure filled by the
BeginPaint function.
Like the answer of #Stra, use FillRect to fill the background.
Or initialize hbrBackground:
hInstanceGlobal = hInstance;
const char CLASSNAME[] = "APIOPENGL";
WNDCLASS cl = { };
cl.lpfnWndProc = wndproc;
cl.hCursor = LoadCursor(NULL, IDC_ARROW);
cl.hInstance = hInstance;
cl.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
cl.lpszClassName = CLASSNAME;
RegisterClass(&cl);
Then you don’t need to process the WM_SIZE message.
In addition, you don’t need to call GetKeyState to get the VK_RMENU key Presse event, just process the WM_SYSKEYDOWN message and Indicates whether the key is an extended key:
/*case WM_SIZE:
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
PostMessage(hWnd, WM_PAINT, 0, 0);
return 0;*/
case WM_SYSKEYDOWN:
if (VK_MENU == wParam)
{
BOOL bit = (lParam >> 24) & 1;
if (bit)
cout << "Pressed" << endl;
}
return 0;

C++ CreateDIBitmap return null if move windows

I'm writing a demo program to load an image from file to OpenCV cv::Mat format, then convert to bitmap and display in Win32 windows. This is full source code:
// Win32
#include <Windows.h>
// OpenCV
#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#pragma comment(lib, "opencv_core310d.lib")
#pragma comment(lib, "opencv_imgcodecs310d.lib")
// Marco
#define WIN_CLASS_NAME TEXT("DisplayTest")
#define WIN_NAME TEXT("Display Test")
#define IMAGE_SRC "./image.jpg"
// Global object
cv::Mat imgMat;
HWND hwndWindow;
// Convert cv::Mat data to bitmap
HBITMAP ConvertCVMatToBMP(cv::Mat frame)
{
auto convertOpenCVBitDepthToBits = [](const INT32 value) {
auto regular = 0u;
switch (value) {
case CV_8U:
case CV_8S:
regular = 8u;
break;
case CV_16U:
case CV_16S:
regular = 16u;
break;
case CV_32S:
case CV_32F:
regular = 32u;
break;
case CV_64F:
regular = 64u;
break;
default:
regular = 0u;
break;
}
return regular;
};
auto imageSize = frame.size();
if (imageSize.width && imageSize.height) {
auto headerInfo = BITMAPINFOHEADER{};
ZeroMemory(&headerInfo, sizeof(headerInfo));
headerInfo.biSize = sizeof(headerInfo);
headerInfo.biWidth = imageSize.width;
headerInfo.biHeight = -(imageSize.height); // negative otherwise it will be upsidedown
headerInfo.biPlanes = 1;// must be set to 1 as per documentation frame.channels();
const auto bits = convertOpenCVBitDepthToBits(frame.depth());
headerInfo.biBitCount = frame.channels() * bits;
auto bitmapInfo = BITMAPINFO{};
ZeroMemory(&bitmapInfo, sizeof(bitmapInfo));
bitmapInfo.bmiHeader = headerInfo;
bitmapInfo.bmiColors->rgbBlue = 0;
bitmapInfo.bmiColors->rgbGreen = 0;
bitmapInfo.bmiColors->rgbRed = 0;
bitmapInfo.bmiColors->rgbReserved = 0;
auto dc = GetDC(nullptr);
assert(dc != nullptr && "Failure to get DC");
auto bmp = CreateDIBitmap(dc,
&headerInfo,
CBM_INIT,
frame.data,
&bitmapInfo,
DIB_RGB_COLORS);
assert(bmp != nullptr && "Failure creating bitmap from captured frame");
DeleteDC(dc);
return bmp;
}
return nullptr;
}
// Attach image to windows
void attachImage()
{
HBITMAP bitImage = (HBITMAP)ConvertCVMatToBMP(imgMat);
// Display image
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwndWindow, &ps);
HDC imageDC = CreateCompatibleDC(hdc);
BITMAP bm;
HBITMAP imageBmpOld = (HBITMAP)SelectObject(imageDC, (HGDIOBJ)bitImage);
GetObject(bitImage, sizeof(bm), &bm);
BitBlt(
hdc, // tell it we want to draw to the screen
0, 0, // as position 0,0 (upper-left corner)
(int)bm.bmWidth, // width of the rect to draw
(int)bm.bmHeight, // height of the rect
imageDC, // the DC to get the rect from (our image DC)
0, 0, // take it from position 0,0 in the image DC
SRCCOPY // tell it to do a pixel-by-pixel copy
);
SelectObject(imageDC, (HGDIOBJ)imageBmpOld);
DeleteDC(imageDC);
DeleteObject((HGDIOBJ)imageBmpOld);
EndPaint(hwndWindow, &ps);
}
// WndProc callback
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
switch (message) {
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
attachImage();
break;
default:
return (DefWindowProc(hwnd, message, wparam, lparam));
}
}
// Register class
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASS wc = { 0 };
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = WIN_CLASS_NAME;
wc.style = CS_HREDRAW | CS_VREDRAW;
return RegisterClass(&wc);
}
int main(int argc, char* argv[])
{
// Register class
char t[500];
GetConsoleTitleA(t, 500);
HWND hwndConsole = FindWindowA(NULL, t);
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndConsole, GWL_HINSTANCE);
MyRegisterClass(hInstance);
// Init data
imgMat = cv::imread(IMAGE_SRC);
// Create Win32 windows
hwndWindow = CreateWindow(WIN_CLASS_NAME, WIN_NAME, WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
ShowWindow(hwndWindow, SW_SHOWNORMAL);
UpdateWindow(hwndWindow);
MSG msg;
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(109));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0)) {
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
This code worked fine for me (Windows 10):
But if it running on Windows 7, after quickly drag and move the windows so that it "go out of" the screen:
And this is the result after move the window back into screen:
In this case, assert(bmp != nullptr) will fall and the program exit suddenly.
This does not happen on Windows 10!
Why CreateDIBitmap return null in this case???
SelectObject doesn't create a handle. In the function below you don't create imageBmpOld and you are not responsible for destroying it. But you did create bitImage (it is created in ConvertCVMatToBMP) and you should destroy bitImage at the end.
// Attach image to windows
void attachImage()
{
HBITMAP bitImage = (HBITMAP)ConvertCVMatToBMP(imgMat);
...
HBITMAP imageBmpOld = (HBITMAP)SelectObject(imageDC, (HGDIOBJ)bitImage);
...
SelectObject(imageDC, imageBmpOld);
DeleteDC(imageDC);
//DeleteObject((HGDIOBJ)imageBmpOld); <<== remove this line
DeleteObject(bitImage); //add this
EndPaint(hwndWindow, &ps);
}
Cleanup for GetDC is done by ReleaseDC, not DeleteDC
HBITMAP ConvertCVMatToBMP(cv::Mat frame)
{
...
auto dc = GetDC(nullptr);
assert(dc != nullptr && "Failure to get DC");
auto bmp = CreateDIBitmap(dc,
&headerInfo, CBM_INIT, frame.data, &bitmapInfo, DIB_RGB_COLORS);
assert(bmp != nullptr && "Failure creating bitmap from captured frame");
//DeleteDC(dc); <<== remove
ReleaseDC(nullptr, dc); //<<== add
...
}
Your window procedure doesn't always return a value. Add return 0; at the end.
The function attachImage() does not attach the image to window. It only paints the image on window. The way you have set it up it only works in response to WM_PAINT so you should really rename it OnPaint()
Also FindWindow(NULL, title) is not reliable because more than one window can have the same title. You should use GetConsoleWindow to get that window handle:
int main()
{
HWND hwndConsole = GetConsoleWindow();
...
}
Better yet, you could use WinMain entry point to skip the console window. The easiest way is to create a new project in your IDE, it should let you select "win32 project" (not "win32 console project")
//int main()
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
{
...
}

WinMain/Win32 Window not displaying, but shows up in Processes tab of Task Manager

I'm a newbie to c++, and I'm stuck on displaying the window. I'm not getting any errors, but my Window is not displaying on the desktop. When I open the task manager, it appears under the 'Proccesses' tab. I haven't been finding any solutions to this problem, so any help is appreciated. Thanks! :)
**Note: I'm using Microsoft Visual Studio 2012
**Note: Not exactly a newbie to c++, but more to creating a win32 application
#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
static TCHAR WindowClass[] = L"Window";
LRESULT CALLBACK WindowProc(
HWND WinH,
UINT Msg,
WPARAM wParam,
LPARAM lParam
)
{
switch (Msg)
{
PAINTSTRUCT pntStruct;
static HDC hdc;
case WM_PAINT:
{
BeginPaint(
WinH,
&pntStruct
);
TextOut(hdc,
5, 5,
L"Hello, World!", _tcslen(L"Hello, World!"));
//pntStruct.rcPaint
EndPaint(
WinH,
&pntStruct
);
} break;
case WM_SIZE:
{
} break;
case WM_MOVE:
{
} break;
case WM_DESTROY:
{
} break;
case WM_CLOSE:
{
} break;
default:
{
return DefWindowProc(WinH, Msg, wParam, lParam);
} break;
case WM_ACTIVATEAPP:
{
if (WM_ACTIVATEAPP)
{
OutputDebugStringA("WM_ACTIVEAPP->TRUE");
}
else
{
OutputDebugStringA("WM_ACTIVEAPP->FALSE");
}
} break;
}
return 0;
};
int WINAPI WinMain(
HINSTANCE Window,
HINSTANCE PrevInstance,
LPSTR Cmd,
int CmdShow
)
{
WNDCLASSEX wclass;
//wclass.cbSize = sizeof(WNDCLASS);
wclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wclass.lpfnWndProc = WindowProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = Window;
//wclass.hIcon; TODO: CREATE ICON
//wclass.hCursor;
//wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wclass.lpszMenuName = NULL;
wclass.lpszClassName = (LPCTSTR)WindowClass;
// HICON hIconSm;
RegisterClassEx(&wclass);
HWND CreateWin = CreateWindow(
WindowClass,
L"NAME OF WINDOW",
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,//WIDTH:[TODO]->Make custom width to fit window
CW_USEDEFAULT,//HEIGHT:[TODO]->Make custom width to fit window
0,
0,
Window,
0
);
ShowWindow(CreateWin, CmdShow);
UpdateWindow(CreateWin);
MSG message;
while (GetMessage(&message, NULL, 0, 0) > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
};
return 0;
};
There are lots of things wrong with this code.
You are declaring WindowClass as a TCHAR[], but initializing it with a wchar_t[]. Same thing with the lpString parameter of TextOut(). That will only work if UNICODE is defined for the project, otherwise you will get a compiler error. When you use TCHAR, you need to wrap string literals with the TEXT() macro so they use the correct character type. Otherwise, stop using TCHAR and just use Unicode APIs for everything. You only need to use TCHAR if your code needs to support both ANSI (Win9x/ME) and Unicode (NT4+) compilations. Nobody really supports Win9x/Me anymore, so new code should focus on just Unicode APIs.
You are not zeroing the contents of the WNDCLASSEX structure, so all of the fields that you have intentionally commented out and not assigned values to (most importantly, the cbSize field) will contain random values from the stack. That is likely to cause RegisterClassEx() to fail, which you are not checking for. To avoid this problem, ALWAYS zero out API structures before using them. This is especially important for structures that grow in size over time (when newer Windows releases introduce new structure fields). Such structures typically have a cbSize field so the API knows which version of the structure you are using, so you must provide an accurate value. And you need to zero out any unused fields so you do not get unexpected behavior from the API.
You are not checking if CreateWindow() fails, such as a side effect of RegisterClassEx() failing.
Your WindowProc() is supposed to pass unhandled messages to DefWindowProc(), but you are not doing that. Most of your case blocks are simply discarding messages so Windows cannot process them. Is that what you really want? I doubt it. In particular, the default behavior of DefWindowProc() for WM_CLOSE is to destroy the window, triggering the WM_DESTROY message.
Your WM_DESTROY handler is not calling PostQuitMessage() to put a WM_QUIT message into the calling thread's message queue so GetMessage() can return 0 to break your message loop and let the app exit.
Your WM_PAINT handler is not using the HDC that BeginPaint() provides to you, you are drawing using an uninitialized HDC variable.
With all of that said, try something more like this:
#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h> // Or: remove this
static TCHAR WindowClass[] = TEXT("Window");
// or: static WCHAR WindowClass[] = L"Window";
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_PAINT:
{
static const TCHAR* HelloWorld = TEXT("Hello, World!");
// or: const WCHAR* HelloWorld = L"Hello, World!";
PAINTSTRUCT pntStruct = {0};
HDC hdc = BeginPaint(hWnd, &pntStruct);
TextOut(hdc, 5, 5, HelloWorld, _tcslen(HelloWorld));
// or: TextOutW(hdc, 5, 5, HelloWorld, lstrlenW(HelloWorld));
EndPaint(hWnd, &pntStruct);
break;
}
case WM_SIZE:
{
//...
break;
}
case WM_MOVE:
{
//...
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
case WM_CLOSE:
{
//...
break;
}
case WM_ACTIVATEAPP:
{
if (WM_ACTIVATEAPP)
{
OutputDebugString(TEXT("WM_ACTIVEAPP->TRUE"));
// or: OutputDebugStringW(L"WM_ACTIVEAPP->TRUE");
}
else
{
OutputDebugString(TEXT("WM_ACTIVEAPP->FALSE"));
// or: OutputDebugStringW(L"WM_ACTIVEAPP->FALSE");
}
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wclass = {0}; // Or: WNDCLASSEXW
wclass.cbSize = sizeof(wclass);
wclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wclass.lpfnWndProc = &WindowProc;
wclass.cbClsExtra = 0;
wclass.cbWndExtra = 0;
wclass.hInstance = hInstance;
wclass.hIcon = NULL; // TODO: CREATE ICON
wclass.hCursor = NULL;
wclass.hbrBackground = NULL;//(HBRUSH)(COLOR_WINDOW+1);
wclass.lpszMenuName = NULL;
wclass.lpszClassName = WindowClass;
wclass.hIconSm = NULL;
if (!RegisterClassEx(&wclass)) // Or: RegisterClassExW()
{
// error! Use GetLastError() to find out why...
return 0;
}
HWND hCreateWin = CreateWindow( // Or: CreateWindowW()
WindowClass,
TEXT("NAME OF WINDOW"), // Or: L"NAME OF WINDOW"
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,//WIDTH:[TODO]->Make custom width to fit window
CW_USEDEFAULT,//HEIGHT:[TODO]->Make custom width to fit window
0,
0,
hInstance,
0
);
if (!hCreateWin)
{
// error! Use GetLastError() to find out why...
return 0;
}
ShowWindow(hCreateWin, nCmdShow);
UpdateWindow(hCreateWin);
MSG message;
while (GetMessage(&message, NULL, 0, 0) > 0)
{
TranslateMessage(&message);
DispatchMessage(&message);
};
return 0;
};

Importing a BitMap makes my Window Lagg

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.

Background changes after images are drawn on the screen

We are learning about windows raw touch events in class using Visual Studios 2012 in C++. I got my demo working and it does exactly what it is supposed to, which is drawing circles beneath your fingertips to detect that a touch event has been raised. But after a certain time has passed and if you are still pressing on the screen with the circles drawn the screen turns blue! The circles still show but they are blue as well with black contours and I can still move them around. I showed the professor and he can't seem to figure it out which is why I came here. Can anyone take a look at my code to let me know what seems to be the cause of it?
// GT_HelloWorldWin32.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c
#ifndef WINVER // Specifies that the minimum required platform is Windows 7.
#define WINVER 0x0601 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows 7.
#define _WIN32_WINNT 0x0601 // Change this to the appropriate value to target other versions of Windows.
#endif
#include <windows.h> // for windows touch
#include <windowsx.h> // included for point conversion
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include "wtypes.h"
#include <iostream>
using namespace std;
// The main window class name.
TCHAR szWindowClass[] = _T("win32app");
// The string that appears in the application's title bar.
TCHAR szTitle[] = _T("Hello World!");
//Instancing the handler
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//Maximum ammount of touches allowed
#define MAXPOINTS 10
// You will use this array to track touch points
int points[MAXPOINTS][2];
// You will use this array to switch the color / track ids
int idLookup[MAXPOINTS];
// You can make the touch points larger
// by changing this radius value
static int radius = 30;
// There should be at least as many colors
// as there can be touch points so that you
// can have different colors for each point
COLORREF colors[] = { RGB(153,255,51),
RGB(153,0,0),
RGB(0,153,0),
RGB(255,255,0),
RGB(255,51,204),
RGB(0,0,0),
RGB(0,153,0),
RGB(153, 255, 255),
RGB(153,153,255),
RGB(0,51,153)
};
int wmId, wmEvent, i, x, y, index;
UINT cInputs;
PTOUCHINPUT pInputs;
POINT ptInput;
// This function is used to return an index given an ID
int GetContactIndex(int dwID){
for (int i=0; i < MAXPOINTS; i++){
if (idLookup[i] == -1){
idLookup[i] = dwID;
return i;
}else{
if (idLookup[i] == dwID){
return i;
}
}
}
// Out of contacts
return -1;
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wcex;
int width = 0, height = 0; // Screen resolution
GetScreenResolution(width, height);
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
hInst = hInstance; // Store instance handle in our global variable
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
800, 600,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd) {
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
// register the window for touch instead of gestures
RegisterTouchWindow(hWnd, 0);
// the following code initializes the points
for (int i=0; i< MAXPOINTS; i++){
points[i][0] = -1;
points[i][1] = -1;
idLookup[i] = -1;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes touch messages for the main window.
//
// WM_TOUCH - handles WM_TOUCH messages in the application
// WM_DESTROY - post a quit message and return
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// For double buffering
static HDC memDC = 0;
static HBITMAP hMemBmp = 0;
HBITMAP hOldBmp = 0;
//For drawing / fills
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_TOUCH:
//LOWORD(wParam) = number of touch points in this message
//HIWORD(wParam) = reserved for future use
//lParam = handle for use with GetTouchInputInfo
cInputs = LOWORD(wParam);
pInputs = new TOUCHINPUT[ cInputs ];
if(pInputs)
{
if( GetTouchInputInfo((HTOUCHINPUT)lParam, cInputs, pInputs, sizeof(TOUCHINPUT)) )
{
for (int i=0; i < static_cast<INT>(cInputs); i++)
{
TOUCHINPUT ti = pInputs[i];
index = GetContactIndex(ti.dwID);
if(ti.dwID != 0 && index < MAXPOINTS )
{
//get screen corrdinates of touch
ptInput.x = TOUCH_COORD_TO_PIXEL(ti.x);
ptInput.y = TOUCH_COORD_TO_PIXEL(ti.y);
//get coordinates relative to the top left of the application window
ScreenToClient(hWnd, &ptInput);
if(ti.dwFlags & TOUCHEVENTF_UP)
{
points[index][0] = -1;
points[index][1] = -1;
}
else
{
points[index][0] = ptInput.x;
points[index][1] = ptInput.y;
}
}
}
}
CloseTouchInputHandle((HTOUCHINPUT)lParam);
delete [] pInputs;
}
InvalidateRect(hWnd, NULL, FALSE);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
RECT client;
GetClientRect(hWnd, &client);
//START DOUBLE BUFFERING
if (!memDC)
{
memDC = CreateCompatibleDC(hdc);
}
hMemBmp = CreateCompatibleBitmap(hdc, client.right, client.bottom);
hOldBmp = (HBITMAP)SelectObject(memDC, hMemBmp);
FillRect(memDC, &client, CreateSolidBrush(RGB(255,255,255)));
//Draw Touched Points
for (i=0; i < MAXPOINTS; i++)
{
SelectObject( memDC, CreateSolidBrush(colors[i]));
x = points[i][0];
y = points[i][1];
if (x >0 && y>0)
{
Ellipse(memDC, x - radius, y - radius, x + radius, y + radius);
}
}
BitBlt(hdc, 0,0, client.right, client.bottom, memDC, 0,0, SRCCOPY);
EndPaint(hWnd, &ps);
ReleaseDC(hWnd, hdc);
//DeleteObject(hMemBmp);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
I see the problem now. You have a GDI resource leak.
In two places you call CreateSolidBrush but you never delete the brushes you created. You do it here
FillRect(memDC, &client, CreateSolidBrush(RGB(255,255,255)));
and here
SelectObject( memDC, CreateSolidBrush(colors[i]));
Really, you should assign the result of eachCreateSolidBrush function to a HBRUSH and then call DeleteObject on it when you've finished with it.
You also need to release your bitmap: DeleteObject(hMemBmp) which you have commented out and also remove the call to ReleaseDC as I said in the comments.
Generally, you should keep a careful track of all of the GDI objects you have created and make sure you delete them when you've finished with them.