ok i when it try to insert two values in two different vectors it won't work the first one will work but the second won't be setted.
// Xstrike.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Xstrike.h"
#include <vector>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
RECT *rect;
const UINT_PTR EVERYTHING_ID=0x1;
const UINT_PTR LBUTTONDOWN_ID=0x3;
const UINT_PTR TDENEMIE1_ID=0x4;
const UINT_PTR TAENEMIE1_ID=0x5;
int conno=2;
int side=0;
int cEnemie1=0;
int dEnemie1=1;
int aEnemie1=0;
int sEnemie1=1;
bool e1=true;
time_t now;
time_t tEnemie1;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
vector <POINT> vRegularShots;
vector <POINT> vS1Enemie1;
vector <POINT> vS2Enemie1;
VOID Paint(HDC hdc, HWND hWnd)
{
hdc=GetDC(hWnd);
HDC memDC=CreateCompatibleDC(hdc);
HBITMAP hMemMap=CreateCompatibleBitmap(hdc, 225, 350);
HBITMAP hOldMap=(HBITMAP)SelectObject(memDC, hMemMap);
Graphics draw(memDC);
// Drawing
Image bg(L"bg.jpg");
draw.DrawImage(&bg, 0, 0);
// Regular shots
Image shot(L"RegularShots.png");
long s=vRegularShots.size();
// Draw shots
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
draw.DrawImage(&shot, vRegularShots[index].x, vRegularShots[index].y);
}
// Update the shots
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
vRegularShots[index].y--;
}
// Create Enemies
if(dEnemie1==0)
{
if(cEnemie1<2)
{
if(aEnemie1==0)
{
SetTimer(hWnd, TAENEMIE1_ID, 550, NULL);
}
aEnemie1=1;
cEnemie1++;
}
else
{
KillTimer(hWnd, TDENEMIE1_ID);
}
dEnemie1=1;
}
// Draw enemies
for(long index=0; index < (long)vS1Enemie1.size(); ++index)
{
Image iEnemie1(L"Enemie1.png");
draw.DrawImage(&iEnemie1, vS1Enemie1[index].x, vS1Enemie1[index].y);
}
for(long index=0; index < (long)vS2Enemie1.size(); ++index)
{
Image iEnemie1(L"Enemie1.png");
draw.DrawImage(&iEnemie1, vS2Enemie1[index].x, vS2Enemie1[index].y);
}
// Update enemies
for(long index=0; index < (long)vS1Enemie1.size(); index++)
{
vS1Enemie1[index].x++;
vS1Enemie1[index].y++;
}
for(long index=0; index < (long)vS2Enemie1.size(); index++)
{
vS2Enemie1[index].x--;
vS2Enemie1[index].y++;
}
// Delete enemies
for(long index=0; index < (long)vS1Enemie1.size(); index++)
{
if(vS1Enemie1[index].x>225)
{
vS1Enemie1.erase(vS1Enemie1.begin()+index);
}
}
for(long index=0; index < (long)vS2Enemie1.size(); index++)
{
if(vS2Enemie1[index].x>225)
{
vS2Enemie1.erase(vS2Enemie1.begin()+index);
}
}
BitBlt(hdc, 0, 0, 225, 350, memDC, 0, 0, SRCCOPY);
ReleaseDC(hWnd, hdc);
SelectObject(memDC, hOldMap);
DeleteObject(hMemMap);
DeleteDC(memDC);
}
VOID CheckDead()
{
for(long index=0; index < (long)vRegularShots.size(); ++index)
{
vRegularShots[index].x, vRegularShots[index].y;
}
}
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize GDI+.
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_XSTRIKE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_XSTRIKE));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
GdiplusShutdown(gdiplusToken);
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage are only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
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_XSTRIKE));
wcex.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR));
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_XSTRIKE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX),
CW_USEDEFAULT, 0, 225, 350, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
POINT pt;
POINT pts;
switch (message)
{
case WM_CREATE:
SetTimer(hWnd, EVERYTHING_ID, 1, NULL);
break;
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);
Paint(hdc, hWnd);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONDOWN:
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
if(conno==1)
{
conno++;
}
else
{
pt.x+=18;
conno--;
}
vRegularShots.push_back(pt);
SetTimer(hWnd, LBUTTONDOWN_ID, 350, NULL);
InvalidateRect(hWnd, rect, false);
break;
case WM_LBUTTONUP:
KillTimer(hWnd, LBUTTONDOWN_ID);
break;
case WM_TIMER:
switch(wParam)
{
case EVERYTHING_ID:
if(e1==true)
{
now=time(NULL);
tEnemie1=now+1;
e1=false;
}
now=time(NULL);
if(now==tEnemie1)
{
SetTimer(hWnd, TDENEMIE1_ID, 550, NULL);
}
InvalidateRect(hWnd, rect, false);
break;
case LBUTTONDOWN_ID:
GetCursorPos(&pt);
ScreenToClient(hWnd, &pt);
if(conno==1)
{
conno++;
}
else
{
pt.x+=18;
conno--;
}
vRegularShots.push_back(pt);
break;
case TDENEMIE1_ID:
pt.y=5;
pt.x=-26;
vS1Enemie1.push_back(pt);
pt.y=52;
pt.x=251;
vS2Enemie1.push_back(pt);
dEnemie1=0;
InvalidateRect(hWnd, rect, false);
break;
case TAENEMIE1_ID:
InvalidateRect(hWnd, rect, false);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
the values in will be inserted in vS1Enemie1 but not in vS2Enemie1.
any idea?
When you put a breakpoint on a particular line of code in visual studio and then hit that breakpoint, then line of code where you put the breakpoint hasn't actually executed yet.
For example, let's let the "*" represent where you've placed your breakpoint in visual studio.
int a = 0;
int b = 0;
a = 3;
* b = 4;
When you hit the breakpoint, it is after a and b were declared, and after a has been set to 3, but BEFORE the line "b = 4;" has had a chance to execute. Most debuggers do this so you have the opportunity to step into the line of code you put your breakpoint on. For example, I might have had "myComplicatedFunction(a, b);" instead of "b = 4". By stopping before that line of code has a chance to execute, the debugger gives you a chance to examine data or step into a function to see what's happening before what's happening before everything goes wrong.
Related
I have been taking reference for my project from this source:
https://learn.microsoft.com/en-us/windows/win32/directwrite/getting-started-with-directwrite
My goal is very simple:
Follow the guidance in the link given below and somehow get the output that the link finally gets. I would have been glad if I at least got the intermediate output.
However, unfortunately my project always seems to compile with a nullptr error, and these are my findings so far. I'm working in an area out of my expertise and I was only able to find the following:
I am not sure if I have created the SimpleText class according to what has been given in the link
I am probably not linking the window handler correctly to the Simple Text class object
Here is my code(it seems big, but it is only just class definition + basic window creation, honestly nothing else at all)
// cvvvv.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "cvvvv.h"
#include<dwrite.h>
#include<d2d1.h>
#include<iostream>
#include<fstream>
#include<stdio.h>
using namespace std;
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
// *********************************************************************************
//HRESULT HasCharacter(
// UINT32 unicodeValue,
// BOOL* exists
//);
long const uniLast = 1114111;
//UINT32 codePoints[uniLast];
//UINT32 codePointsCount = uniLast;
//UINT16 glyphIndices[uniLast];
long long SairamAll;
// https://learn.microsoft.com/en-us/windows/win32/directwrite/getting-started-with-directwrite //
///// Part 1: Declare DirectWrite and Direct2D Resources. /////
// 1. In your class header file(SimpleText.h), declare pointers to IDWriteFactoryand IDWriteTextFormat interfaces as private members.
//IDWriteFactory* pDWriteFactory_;
//IDWriteTextFormat* pTextFormat_;
// 3. Declare pointers to ID2D1Factory, ID2D1HwndRenderTarget, and ID2D1SolidColorBrush interfaces for rendering the text with Direct2D.
//ID2D1Factory* pD2DFactory_;
//ID2D1HwndRenderTarget* pRT_;
//ID2D1SolidColorBrush* pBlackBrush_;
///// Part 2: Create Device Independent Resources. /////
template <class T> void SafeRelease(T** ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}
class SimpleText {
private:
// 2. Declare members to hold the text string to render and the length of the string.
IDWriteFactory* pDWriteFactory_;
IDWriteTextFormat* pTextFormat_;
const wchar_t* wszText_;
UINT32 cTextLength_;
ID2D1Factory* pD2DFactory_;
ID2D1HwndRenderTarget* pRT_;
ID2D1SolidColorBrush* pBlackBrush_;
HRESULT hr;
RECT rc;
HWND hwnd_;
float dpiScaleX_, dpiScaleY_;
public:
SimpleText() {
hr = CreateDeviceResources();
if (SUCCEEDED(hr))
{
pRT_->BeginDraw();
pRT_->SetTransform(D2D1::IdentityMatrix());
pRT_->Clear(D2D1::ColorF(D2D1::ColorF::White));
// Call the DrawText method of this class.
hr = DrawText();
if (SUCCEEDED(hr))
{
hr = pRT_->EndDraw(
);
}
}
if (FAILED(hr))
{
DiscardDeviceResources();
}
}
void CreateDeviceIndependentResources() {
hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&pD2DFactory_);
if (SUCCEEDED(hr))
{
hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&pDWriteFactory_)
);
}
wszText_ = L"Hello World using DirectWrite!";
cTextLength_ = (UINT32)wcslen(wszText_);
if (SUCCEEDED(hr))
{
hr = pDWriteFactory_->CreateTextFormat(
L"Gabriola", // Font family name.
NULL, // Font collection (NULL sets it to use the system font collection).
DWRITE_FONT_WEIGHT_REGULAR,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
72.0f,
L"en-us",
&pTextFormat_
);
}
// Center align (horizontally) the text.
if (SUCCEEDED(hr))
{
hr = pTextFormat_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
}
if (SUCCEEDED(hr))
{
hr = pTextFormat_->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
}
}
HRESULT CreateDeviceResources() {
GetClientRect(hwnd_, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
if (!pRT_)
{
// Create a Direct2D render target.
hr = pD2DFactory_->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hwnd_,
size
),
&pRT_
);
// Create a black brush.
if (SUCCEEDED(hr))
{
hr = pRT_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&pBlackBrush_
);
}
}
return hr;
}
void DiscardDeviceResources() {
SafeRelease(&pRT_);
SafeRelease(&pBlackBrush_);
}
HRESULT DrawText() {
D2D1_RECT_F layoutRect = D2D1::RectF(
static_cast<FLOAT>(rc.left) / dpiScaleX_,
static_cast<FLOAT>(rc.top) / dpiScaleY_,
static_cast<FLOAT>(rc.right - rc.left) / dpiScaleX_,
static_cast<FLOAT>(rc.bottom - rc.top) / dpiScaleY_
);
pRT_->DrawText(
wszText_, // The string to render.
cTextLength_, // The string's length.
pTextFormat_, // The text format.
layoutRect, // The region of the window where the text will be rendered.
pBlackBrush_ // The brush used to draw the text.
);
return hr;
}
};
// *********************************************************************************
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_CVVVV, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CVVVV));
MSG msg;
SimpleText s;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
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_CVVVV));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_CVVVV);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
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);
// 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;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
I am sorry if I am asking for too much. But I am honestly stuck, and very surprisingly, I was not able to find this implemented anywhere on the net(hope I did not miss something that was obviously there).
I am trying to create a simple Tic-Tac-Toe game for a school project. I don't really know how to work with windows and I just want to work with others' code, using the default "Windows Desktop Application" (C++) in Visual Studio, but it keeps giving me this error message:
identifier "hWnd" is undefined
I don't really know how to work with this (at school, we work with some basic console application stuff) and I don't know how to define hWnd.
Can somebody help me?
// Proba2.cpp : Defines the entry point for the application.
//
#include <windows.h>
#include "framework.h"
#include "Proba2.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
POINT MousePos;
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_PROBA2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PROBA2));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
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_PROBA2));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PROBA2);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
int lepeskoz;
int hatar;
int tabla[10][10];
void kattintas(POINT mouse);
void tabla_kirajzol();
void init();
void bejeloles(int x, int y, int azonosito);
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
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_CREATE:
init();
return 0;
case WM_LBUTTONDOWN:
MousePos.x = LOWORD(lParam);
MousePos.y = HIWORD(lParam);
kattintas(MousePos);
return 0;
case WM_PAINT:
tabla_kirajzol();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
void kattintas(POINT mouse)
{
int x_adat = (mouse.x / lepeskoz);
int y_adat = (mouse.y / lepeskoz);
if (x_adat < 3 && y_adat < 3)
{
if (tabla[y_adat][x_adat] > 0) return;
}
}
void init()
{
lepeskoz = (400 - 30) / 3;
hatar = (4 * lepeskoz) + 5;
}
void bejeloles(int x, int y, int azonosito)
{
tabla[y][x] = azonosito;
tabla_kirajzol();
}
void palya()
{
int i;
PAINTSTRUCT ps;
HBRUSH hBrush;
RECT rect;
HDC hdc2;
HPEN vonalstilus;
{
vonalstilus = CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
hdc2 = GetDC(hWnd);
BeginPaint(hWnd, &ps);
hBrush = CreateSolidBrush(RGB(204, 204, 204));
SetRect(&rect, 0, 0, 400, 600);
FillRect(hdc2, &rect, hBrush);
EndPaint(hWnd, &ps);
SelectObject(hdc2, vonalstilus);
for (i = 5; i < hatar; i += lepeskoz)
{
MoveToEx(hdc2, i, 5, NULL);
LineTo(hdc2, i, hatar - lepeskoz);
}
for (i = 5; i < hatar; i += lepeskoz)
{
MoveToEx(hdc2, 5, i, NULL);
LineTo(hdc2, hatar - lepeskoz, i);
}
ReleaseDC(hWnd, hdc2);
DeleteObject(vonalstilus);
}
}
void tabla_kirajzol()
{
int x;
int y;
int korx, kory, kor_szelesseg;
PAINTSTRUCT ps;
HBRUSH hBrush;
HDC hdc2;
HPEN vonalstilus;
vonalstilus = CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
hBrush = CreateSolidBrush(RGB(34, 204, 204));
hdc2 = GetDC(hWnd);
BeginPaint(hWnd, &ps);
SelectObject(hdc2, vonalstilus);
palya();
for (y = 0; y < 10; ++y)
for (x = 0; x < 10; ++x)
{
korx = x * lepeskoz + 5 + (lepeskoz / 2);
kory = y * lepeskoz + 5 + (lepeskoz / 2);
kor_szelesseg = (lepeskoz / 2) - 5;
if (tabla[y][x] > 0)
{
if (tabla[y][x] == 1) {
hBrush = CreateSolidBrush(RGB(34, 204, 204)); SelectObject(hdc2, hBrush);
Ellipse(hdc2, korx - kor_szelesseg, kory - kor_szelesseg, korx + kor_szelesseg, kory + kor_szelesseg);
}
else if (tabla[y][x] == 2) {
hBrush = CreateSolidBrush(RGB(204, 204, 34)); SelectObject(hdc2, hBrush);
Rectangle(hdc2, korx - kor_szelesseg, kory - kor_szelesseg, korx + kor_szelesseg, kory + kor_szelesseg);
}
}
}
EndPaint(hWnd, &ps);
ReleaseDC(hWnd, hdc2);
DeleteObject(hBrush);
DeleteObject(vonalstilus);
}
bejeloles() isn't used, remove it.
Your void tabla_kirajzol(); should have this signature: void tabla_kirajzol(HWND hWnd); to enable passing the hWnd variable to the function.
Your void palya(); should, for the same reason as above, be void palya(HWND hWnd);
In the message loop, do this to pass hWnd to tabla_kirajzol:
case WM_PAINT:
tabla_kirajzol(hWnd);
break;
In tabla_kirajzol, call palya like this: palya(hWnd);
Disclaimer: The above is untested because you didn't make a Minimal, Reproducible Example, so there could be more errors
Having a window with gif and some elements c++ winapi(Non-MFC) using gdi+. SO I want to make transparent elements(Edit,Static,Button). I want to make transparent gray background of elements.
I have tried to handle WM_CTLCOLORSTATIC and adding style WS_EX_TRANSPARENT and m. but it didn't give correct result. But when I handle WM_CTLCOLORSTATIC with code:
hdcStatic = (HDC) wParam;
SetTextColor(hdcStatic, RGB(0,0,0));
SetBkMode (hdcStatic, TRANSPARENT);
return (LRESULT)GetStockObject(NULL_BRUSH);
And it showed STATIC styles transparent, but I could see background of Windows 10.
Minimum code is:
#include <memory>
#include "Resource.h"
#include <vector>
#include "TESTING.h"
#include "framework.h"
#include <algorithm>
#include <windows.h>
#include <objidl.h>
#include <GdiPlus.h>
#include <gdiplusimaging.h>
#include <shlwapi.h>
#include<CommCtrl.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
#pragma comment (lib,"shlwapi.lib")
#pragma comment (lib,"Comctl32.lib")
#define TIMER_ID 101
static HFONT s_hFont = NULL;
static HWND hWnd;
static HWND hwndText;
static HWND hwndButton;
static HWND hwndLabel;
static HWND hwndCode;
static HWND hwndCode2;
static HWND hwndTime;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK SubWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, UINT_PTR, DWORD_PTR);
int WINAPI _WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
ULONG_PTR m_gdiplusToken;
GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
HMODULE hMod = GetModuleHandle(NULL);
HRSRC hRes = FindResource(hMod, MAKEINTRESOURCEW(MY_GIF_ID), RT_RCDATA);
if (!hRes) MessageBox(NULL, L"hRes!!", L"ERROR", 0);
HGLOBAL hGlobal = LoadResource(hMod, hRes);
if (!hGlobal)MessageBox(NULL, L"hGlobal!!", L"ERROR", 0);
void* pResData = LockResource(hGlobal);
if (!pResData) MessageBox(NULL, L"pResData!!", L"ERROR", 0);
DWORD dwResData = SizeofResource(hMod, hRes);
IStream* pStream = SHCreateMemStream((BYTE*)pResData, dwResData);
if (!pStream) MessageBox(NULL, L"pStream!!", L"ERROR", 0);
Image gif(pStream);
pStream->Release();
MSG msg = { 0 };
WNDCLASS wc = { 0 };
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = NULL; // <= Do not provide a background brush.
wc.lpszClassName = L"anim_gif_player";
if (!RegisterClass(&wc))
return -1;
hWnd = CreateWindow(wc.lpszClassName,
L"",
WS_EX_TOPMOST | WS_CLIPCHILDREN & ~WS_CAPTION & ~WS_SYSMENU,
0, 0, 640, 480, 0, 0, hInstance, &gif);
if (!hWnd) {
MessageBox(0, L"SSSSSSSSSSSSSSSSSSS", L"kkkkkkkkkkkkkkkkkkkkkk", 0);
return -2;
}
hwndLabel = CreateWindowEx(WS_EX_TRANSPARENT,L"STATIC",
NULL,
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
325, 90, 440, 45,
hWnd,
NULL,
NULL,
NULL);
SetWindowSubclass(hwndLabel, SubWndProc, 0, 0);
const TCHAR* fontName = TEXT("Croobie");
const long nFontSize = 24;
HDC hdc = GetDC(hwndLabel);
LOGFONT logFont = { 0 };
logFont.lfHeight = -MulDiv(nFontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
logFont.lfWeight = FW_BOLD;
wcscpy_s(logFont.lfFaceName, fontName);
s_hFont = CreateFontIndirect(&logFont);
SendMessage(hwndLabel, WM_SETFONT, (WPARAM)s_hFont, (LPARAM)MAKELONG(TRUE, 0));
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//DeleteObject(wc.hbrBackground);
return msg.wParam;
}
std::vector<unsigned int> LoadGifFrameInfo(Image* image)
{
// I think animated gifs will always only have 1 frame dimension...
// the "dimension" being the frame count, but I could be wrong about this
int count = image->GetFrameDimensionsCount();
if (count != 1)
return std::vector<unsigned int>();
GUID guid;
if (image->GetFrameDimensionsList(&guid, 1) != 0)
return std::vector<unsigned int>();
int frame_count = image->GetFrameCount(&guid);
auto sz = image->GetPropertyItemSize(PropertyTagFrameDelay);
if (sz == 0)
return std::vector<unsigned int>();
// copy the frame delay property into the buffer backing an std::vector
// of bytes and then get a pointer to its value, which will be an array of
// unsigned ints
std::vector<unsigned char> buffer(sz);
PropertyItem* property_item = reinterpret_cast<PropertyItem*>(&buffer[0]);
image->GetPropertyItem(PropertyTagFrameDelay, sz, property_item);
unsigned int* frame_delay_array = (unsigned int*)property_item[0].value;
// copy the delay values into an std::vector while converting to milliseconds.
std::vector<unsigned int> frame_delays(frame_count);
std::transform(frame_delay_array, frame_delay_array + frame_count, frame_delays.begin(),
[](unsigned int n) {return n * 10; }
);
return frame_delays;
}
void GenerateFrame(Bitmap* bmp, Image* gif)
{
Graphics dest(bmp);
SolidBrush white(Color::White);
dest.FillRectangle(&white, 0, 0, bmp->GetWidth(), bmp->GetHeight());
if (gif)
dest.DrawImage(gif, 0, 0);
}
std::unique_ptr<Bitmap> CreateBackBuffer(HWND hWnd)
{
RECT r;
GetClientRect(hWnd, &r);
return std::make_unique<Bitmap>(r.right - r.left, r.bottom - r.top);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static Image* animated_gif;
static std::unique_ptr<Bitmap> back_buffer;
static std::vector<unsigned int> frame_delays;
static int current_frame;
switch (message) {
case WM_CREATE: {
animated_gif = reinterpret_cast<Image*>(
reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams
);
if (!animated_gif || animated_gif->GetLastStatus() != 0) {
MessageBox(hWnd, L"Unable to load animated gif", L"error", MB_ICONERROR);
return 0;
}
// Create a bitmap the size of the window's clent area
back_buffer = CreateBackBuffer(hWnd);
// get the frame delays and thereby test that this is really an animated gif
frame_delays = LoadGifFrameInfo(animated_gif);
if (frame_delays.empty()) {
MessageBox(hWnd, L"Invalid gif or not an animated gif", L"error", MB_ICONERROR);
return 0;
}
current_frame = 0;
animated_gif->SelectActiveFrame(&FrameDimensionTime, current_frame);
GenerateFrame(back_buffer.get(), animated_gif);
SetTimer(hWnd, TIMER_ID, frame_delays[0], nullptr);
InvalidateRect(hWnd, nullptr, FALSE);
}
break;
case WM_TIMER: {
KillTimer(hWnd, TIMER_ID);
current_frame = (current_frame + 1) % frame_delays.size();
animated_gif->SelectActiveFrame(&FrameDimensionTime, current_frame);
GenerateFrame(back_buffer.get(), animated_gif);
SetTimer(hWnd, TIMER_ID, frame_delays[current_frame], nullptr);
InvalidateRect(hWnd, nullptr, FALSE);
} break;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
Graphics g(hdc);
g.DrawImage(back_buffer.get(), 0, 0);
EndPaint(hWnd, &ps);
} break;
case WM_SIZE: {
back_buffer = CreateBackBuffer(hWnd);
GenerateFrame(back_buffer.get(), animated_gif);
} break;
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK SubWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR, DWORD_PTR) {
switch (msg) {
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc; GetClientRect(hwnd, &rc);
SetTextColor(hdc, Color::Yellow);
SetBkMode(hdc, TRANSPARENT);
wchar_t buf[256] = { 0 };
GetWindowTextW(hwnd, buf, sizeof(buf) / sizeof(*buf));
DrawTextW(hdc, buf, wcslen(buf), &rc, DT_LEFT | DT_TOP);
EndPaint(hwnd, &ps);
return 0;
}
case WM_NCDESTROY://safely remove subclass
RemoveWindowSubclass(hwnd, SubWndProc, 0);
return DefSubclassProc(hwnd, msg, wParam, lParam);
}
return DefSubclassProc(hwnd, msg, wParam, lParam);
}
The WS_EX_TRANSPARENT style doesn’t mean “transparent”; it means
“paint over siblings.”
The style is called “transparent” not because it makes the window
transparent but because it makes transparency possible.
Please refer: Why isn't my transparent static control transparent?
The only way I've found to do this reliably is to sub-class the static control and paint the background manually.
You can catch the WM_ERASEBKGND message and paint the appropriate portion of the underlying bitmap.
Please refer:
Is it possible to make a Static control transparent?
C++ Win32 Static Control Transparent Background
Also, if you want remove grey background, you can change static control background and make it transparent.
Demon of custom static control:
#include "stdafx.h"
#include "Test_WM_CTLCOLORSTATIC.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
HWND hWndStatic;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProcPanel(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_TESTWMCTLCOLORSTATIC, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTWMCTLCOLORSTATIC));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
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_TESTWMCTLCOLORSTATIC));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTWMCTLCOLORSTATIC);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
WNDPROC StaticWndProc = NULL;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{ LRESULT lRes = DefWindowProc(hWnd, message, wParam, lParam);
hWndStatic = CreateWindowEx(0, L"Static", NULL, WS_CHILD | WS_VISIBLE | SS_LEFT, 10, 130, 200, 40, hWnd, NULL, hInst, NULL); //v2 deleted HWND
StaticWndProc = (WNDPROC)SetWindowLong(hWndStatic, GWL_WNDPROC, (LPARAM)WndProcPanel);
return lRes;
}
break;
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_ERASEBKGND:
{
HBRUSH brush;
RECT rect;
brush = CreateSolidBrush(RGB(0, 255, 0));
SelectObject((HDC)wParam, brush);
GetClientRect(hWnd, &rect);
Rectangle((HDC)wParam, rect.left, rect.top, rect.right, rect.bottom);
}
break;
case WM_DESTROY:
SetWindowLong(hWndStatic, GWL_WNDPROC, (LPARAM)StaticWndProc);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
TCHAR szText[] = _T("TestString");;
LRESULT CALLBACK WndProcPanel(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_PAINT)
{
RECT rc;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rc);
SetBkMode(hdc, TRANSPARENT);
DrawText(hdc, szText, _tcslen(szText), &rc, DT_CENTER | DT_VCENTER);
EndPaint(hWnd, &ps);
return 0;
}
return CallWindowProc(StaticWndProc, hWnd, message, wParam, lParam);
}
thx #IInspectable's remind, the best way to subclass controls is to use SetWindowsSubclass, see Subclassing Controls
I'll update the new code later, and I'm sorry for my shallow knowledge.
Updated:
case WM_TIMER: {
KillTimer(hWnd, TIMER_ID);
current_frame = (current_frame + 1) % frame_delays.size();
animated_gif->SelectActiveFrame(&FrameDimensionTime, current_frame);
GenerateFrame(back_buffer.get(), animated_gif);
SetTimer(hWnd, TIMER_ID, frame_delays[current_frame], nullptr);
InvalidateRect(hWnd, nullptr, FALSE);
InvalidateRect(hwndLabel, nullptr, FALSE); //Here add new code
}
Debug Result:
So my task is to create 5 child windows and when key is pressed close windows in other order. But I have a problem, when I close first 2 windows the other ones become inactive so I have to click on it so it could be focused window, but how can I prevent other windows to become inactive?
#include "stdafx.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
int windowsCount = 1;
WCHAR buffer[5];
HWND windows[5];
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
srand(unsigned(time(NULL)));
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_OOP10, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
return FALSE;
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_OOP10));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0)) {
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance) {
WNDCLASSEXW wcex;
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_OOP10));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_OOP10);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, L"Main Window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
SetClassLong(hWnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256)));
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
windows[0] = hWnd;
return TRUE;
}
BOOL CreateChildWindow(HWND hWnd) {
_itoa(windowsCount + 1, (char*)buffer, 10);
SetClassLong(hWnd, GCL_HBRBACKGROUND, (LONG)CreateSolidBrush(RGB(rand() % 256, rand() % 256, rand() % 256)));
HWND childWnd = CreateWindow(szWindowClass, buffer, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, windows[windowsCount - 1], nullptr, hInst, nullptr);
if (!childWnd)
return FALSE;
ShowWindow(childWnd, SW_SHOWDEFAULT);
UpdateWindow(childWnd);
windows[windowsCount++] = childWnd;
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_LBUTTONUP:
{
if (windowsCount < 5) {
if (!CreateChildWindow(hWnd))
return FALSE;
}
}
break;
case WM_CLOSE:
{
if (IDOK == MessageBox(hWnd, L"Are you sure you want to quit?", L"You are leaving the program", MB_OKCANCEL | MB_ICONINFORMATION | MB_DEFBUTTON2)) {
if (windowsCount == 1) {
DestroyWindow(windows[--windowsCount]);
PostQuitMessage(NULL);
break;
}
else
DestroyWindow(windows[--windowsCount]);
}
}
break;
case WM_RBUTTONUP:
SetWindowText(hWnd, L"Changed title!");
break;
case WM_KEYDOWN: {
if (windowsCount == 1) {
DestroyWindow(windows[--windowsCount]);
PostQuitMessage(NULL);
break;
}
else
DestroyWindow(windows[--windowsCount]);
}
break;
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);
// 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;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
UNREFERENCED_PARAMETER(lParam);
switch (message) {
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
This should be part of your application logic. Add event handler to the WM_CLOSE message to all your windows and set focus to the appropriate window that is not closed yet.
Windows cannot decide this for you.
#include "stdafx.h"
// Mario Headers
#include "GameMain.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Mario global variables =================
CGameMain* gGameMain;
HWND hWnd;
PAINTSTRUCT ps;
// ========================================
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
// My unprocess function =====================================
void OnCreate(HWND hWnd)
{
}
void OnKeyUp(WPARAM wParam)
{
switch (wParam) {
case VK_LEFT:
gGameMain->KeyReleased(LEFT);
break;
case VK_UP:
gGameMain->KeyReleased(UP);
break;
case VK_RIGHT:
gGameMain->KeyReleased(RIGHT);
break;
case VK_DOWN:
gGameMain->KeyReleased(DOWN);
break;
}
}
void OnKeyDown(HWND hWnd,WPARAM wParam)
{
switch (wParam) {
case VK_LEFT:
gGameMain->KeyPressed(LEFT);
break;
case VK_UP:
gGameMain->KeyPressed(UP);
break;
case VK_RIGHT:
gGameMain->KeyPressed(RIGHT);
break;
case VK_DOWN:
gGameMain->KeyPressed(DOWN);
break;
}
}
void OnPaint(HWND hWnd)
{
HDC hdc = BeginPaint(hWnd,&ps);
RECT rect;
GetClientRect(hWnd,&rect);
HDC hdcDouble = CreateCompatibleDC(hdc);
HBITMAP hdcBitmap = CreateCompatibleBitmap(hdc,rect.right,rect.bottom);
HBITMAP bmOld = (HBITMAP)SelectObject(hdcDouble, hdcBitmap);
gGameMain->SetHDC(&hdcDouble);
gGameMain->SendMessage(MESSAGE_PAINT);
BitBlt(hdc,0,0,rect.right,rect.bottom,hdcDouble,0,0,SRCCOPY);
SelectObject(hdcDouble,bmOld);
DeleteDC(hdcDouble);
DeleteObject(hdcBitmap);
DeleteDC(hdc);
}
void OnDestroy()
{
gGameMain->isPlaying = false;
EndPaint(hWnd,&ps);
}
// My unprocess function =====================================
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
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_GDIMARIO));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_GDIMARIO);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, 0, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
// ---------------- Start gdiplus ------------------
GdiplusStartup(&gdiToken,&gdiStartInput,NULL);
// -------------------------------------------------
// Init GameMain
gGameMain = new CGameMain();
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
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_KEYDOWN:
OnKeyDown(hWnd,wParam);
break;
case WM_KEYUP:
OnKeyUp(wParam);
break;
case WM_CREATE:
OnCreate(hWnd);
break;
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_DESTROY:
OnDestroy();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_GDIMARIO, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_GDIMARIO));
// Main message loop:
// GameLoop
PeekMessage(&msg,NULL,0,0,PM_NOREMOVE);
while (gGameMain->isPlaying)
{
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (gGameMain->enterNextState) {
gGameMain->SendMessage(MESSAGE_ENTER);
gGameMain->enterNextState = false;
}
gGameMain->SendMessage(MESSAGE_UPDATE);
InvalidateRect(hWnd,NULL,FALSE);
/*if (gGameMain->exitCurrentState) {
gGameMain->SendMessage(MESSAGE_EXIT);
gGameMain->enterNextState = true;
gGameMain->exitCurrentState = false;
}*/
::Sleep(gGameMain->timer);
// Do your game stuff here
}
GdiplusShutdown(gdiToken); // Shut down gdiplus token
return (int) msg.wParam;
}
I use InvalidateRect(hWnd,NULL,FALSE); for repaint window, but the problem I met is when I repaint without any changes in Game struct .
First it paints my logo well, the second time ( just call InvalidateRect(hWnd,NULL,FALSE); without gGameMain->SendMessage(MESSAGE_ENTER); which is init some variables for painting .
Thanks for reading this :)
You're calling BeginPaint() in each wm_paint message, but there's no corresponding call to EndPaint() in the wm_paint message handler. Each BeginPaint() must be matched with a corresponding EndPaint(). Your EndPaint() call in OnDestroy is useless.
Also, don't delete the DC returned by BeginPaint(). It is borrowed, not owned.
Other notes: Try to avoid allocating a new bitmap on every wm_paint message. Allocate the bitmap when the window changes size, and hold onto it to be reused by multiple wm_paint passes.
Also note that you're not optimizing the draw to draw only what has been invalidated in the clip rect. You're drawing everything, blitting everything, and relying on GDI to only take the small portion of the bitmap that is actually in the clip rect. This will become a performance issue as the size of your window/bitmap increases and the number of objects/sprites you have running around on the screen increases. You should only draw things that are visible and within the cliprect.