Related
First of all, this question can be a duplicate but the question doesnt have enough information to solve the problem.
I have two windows in my native Win32 application. The first is a layered window with WS_EX_NOACTIVATE extended style and the second is a normal window. I want the layered one to be non-activatable. The problem is that, when I have two window in the same application, the layered one which must be non-activatable, gets activated when switching between them. But there is no problem when switching between two external windows, one being not belong to my application. How can I solve this problem? Or Can I solve that? Is there anything I missed? The following is a minimal reproducable example (didn't include any error checking for minimality.) Thank you for taking time.
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
void init_device_resources(int cx, int cy, void** rgb);
void update_content();
void set_window_size(int width, int height);
HWND layeredhWnd;
HWND otherhWnd;
WNDCLASSEX wc;
MSG msg;
HDC hdcDesktop;
HDC hdcContent;
POINT dstPoint = { 100, 100 };
SIZE windowSize = { 800, 600 };
BLENDFUNCTION bf;
BITMAPINFO bi;
BYTE* rgb_data = NULL;
HBITMAP hBitmap;
HBITMAP hOldBitmap;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"LayeredWindowClass";
RegisterClassEx(&wc);
wc.lpszClassName = L"OtherWindowClass";
RegisterClassEx(&wc);
layeredhWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_NOACTIVATE,
L"LayeredWindowClass",
L"",
WS_POPUP | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_THICKFRAME,
0, 0,
800, 600,
NULL,
NULL,
hInstance,
NULL);
otherhWnd = CreateWindowEx(NULL,
L"OtherWindowClass",
L"",
WS_OVERLAPPEDWINDOW,
0, 0,
800, 600,
NULL,
NULL,
hInstance,
NULL);
init_device_resources(800, 600, &rgb_data);
set_window_size(800, 600);
ShowWindow(layeredhWnd, nCmdShow);
ShowWindow(otherhWnd, nCmdShow);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
{
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
case WM_ACTIVATE:
{
if(hWnd == layeredhWnd)
update_content();
break;
}
case WM_PAINT:
{
if (hWnd == layeredhWnd)
update_content();
break;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void init_device_resources(int cx, int cy, void** rgb)
{
hdcDesktop = GetDC(NULL);
hdcContent = CreateCompatibleDC(hdcDesktop);
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = cx;
bi.bmiHeader.biHeight = -cy;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = cx * cy * 4;
bi.bmiHeader.biXPelsPerMeter = 0;
bi.bmiHeader.biYPelsPerMeter = 0;
bi.bmiHeader.biClrUsed = 0;
bi.bmiHeader.biClrImportant = 0;
bi.bmiColors[0] = (RGBQUAD){ 0 };
hBitmap = CreateDIBSection(hdcContent, &bi, DIB_RGB_COLORS, rgb, NULL, 0);
for (int i = 0; i < cx * cy * 4; i++)
{
rgb_data[i] = 255;
}
hOldBitmap = SelectObject(hdcContent, hBitmap);
}
void update_content()
{
UpdateLayeredWindow(layeredhWnd, hdcDesktop, &dstPoint,
&windowSize, hdcContent, &(POINT){ 0, 0 }, RGB(0, 0, 0), & bf, ULW_ALPHA);
}
void set_window_size(int width, int height)
{
SetWindowPos(layeredhWnd, NULL, 0, 0, width, height, SWP_NOMOVE);
windowSize = (SIZE){ width, height };
}
Although I still don't understand the cause of the problem, with the help of #IInspectable's guidance and documentation, I was able to prevent the window from being activated by processing the WM_MOUSEACTIVATE message. The updated window procedure is as follows.
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CLOSE:
{
DestroyWindow(hWnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
case WM_MOUSEACTIVATE:
{
if (hWnd == layeredhWnd)
return MA_NOACTIVATE;
break;
}
case WM_ACTIVATE:
{
if(hWnd == layeredhWnd)
update_content();
break;
}
case WM_PAINT:
{
if (hWnd == layeredhWnd)
update_content();
break;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
I Was working on a win32 project which uses the WM_MOVING message from WndProc to detect the new position where window is moved. but when i try to snap the window to left side the LPARAM gives wrong values for just a millisecond and gives the real value after that.
Please have a look into the output:
Left: 0, Right:683
Left: -205, Right:295
Left: 0, Right:683
Left: -205, Right:295
Left: 0, Right:683
Left: -205, Right:295
The real output is -205 but in between I get zero which cause the content of my window to flicker. In my case the position of the content is depend on the window position, so it causes flicker if I receive a wrong value.
Here is what i am trying to achieve : Manually creating acrylic effect
When ever I move the window in this mode (just before the aero snap mode) the value will get changed to zero.
This is only affecting The Top and Left coordinates of the window and also flickers when aero snapping to any sides.
Here is a simple reproduceable example:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
RECT* hostRect;
char buffer[200];
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0,CLASS_NAME,L"Learn to Program Windows",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_MOVING:
{
hostRect = reinterpret_cast<RECT*>(lParam);
sprintf_s(buffer, "Left: %d, Top:%d, Right:%d, Bottom:%d\n", hostRect->left, hostRect->top, hostRect->right, hostRect->bottom);
OutputDebugStringA(buffer);
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Run this program and check the value in output while you move the window to any side for aero snap.
Note: In my case i will not be able to use GetWindowRect() in WM_MOVING, because calling GetWindowRect() slow down the render() function (just a directx painting) in my window.
You can try to make temporary changes to the style of the window.
Here is an example:
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <stdio.h>
#define WM_RESTOREORIGINALSTYLE WM_USER + 1
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
RECT* hostRect;
char buffer[200];
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hwnd = CreateWindowEx(0, CLASS_NAME, L"Learn to Program Windows", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_MOVING:
{
hostRect = reinterpret_cast<RECT*>(lParam);
sprintf_s(buffer, "Left: %d, Top:%d, Right:%d, Bottom:%d\n", hostRect->left, hostRect->top, hostRect->right, hostRect->bottom);
OutputDebugStringA(buffer);
break;
}
case WM_SYSCOMMAND:
{
if (wParam == (SC_MOVE | 2)) wParam = SC_SIZE | 9;
if ((wParam & 0xFFE0) == SC_SIZE && (wParam & 0x000F)) // handles MOVE and SIZE in one "if"
{
long int oldStyle = GetWindowLongW(hwnd, GWL_STYLE);
PostMessageW(hwnd, WM_RESTOREORIGINALSTYLE, GWL_STYLE, oldStyle);
SetWindowLongW(hwnd, GWL_STYLE, oldStyle & 0xFEFEFFFF); // disable WS_MAXIMIZE and WS_MAXIMIZEBOX
DefWindowProcW(hwnd, WM_SYSCOMMAND, wParam, lParam);
return 0;
}
return DefWindowProcW(hwnd, WM_SYSCOMMAND, wParam, lParam);
}
case WM_RESTOREORIGINALSTYLE:
{
if ((long int)wParam == GWL_STYLE)
SetWindowLongW(hwnd, GWL_STYLE, lParam);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
More reference : Win32 prevent window “snap”
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:
This question already has an answer here:
CreateWindow() in Visual C++ always return null
(1 answer)
Closed 4 years ago.
I was trying to make application using win32 and directX now, but I stuck at the first step of my project, which is making window. I tried many things to fix, but it keep saying, failed to create window which means hWnd is null.
This is my code.
app.h
#include <windows.h>
#include <string>
class App
{
public:
App (void);
~App (void);
HRESULT InitApp (HINSTANCE hInstance, int nCmdShow);
//void UpdateApp (void);
HWND window(void) { return m_hWnd; }
private:
static LRESULT CALLBACK WndProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);
private:
HINSTANCE m_hInstance;
HWND m_hWnd;
RECT m_rect;
static bool s_running;
std::string m_className;
}
app.cpp
#include "app.h"
// std::string, c.str()
#include <cstring>
#include <iostream>
bool App::s_running = true;
App::App(void)
{
}
App::~App(void)
{
}
HRESULT App::InitApp(HINSTANCE hInstance, int nCmdShow)
{
m_hInstance = hInstance;
WNDCLASSEX wc = {};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = App::WndProc;
wc.hInstance = m_hInstance;
wc.lpszClassName = "Hello" ;
RECT rc = {0, 0, 800, 600};
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE);
int width = rc.right - rc.left;
int height = rc.bottom - rc.top;
if(!RegisterClassEx(&wc))
{
OutputDebugString("Failed to register win class\n");
return E_FAIL;
}
m_hWnd = CreateWindow("Hello", "Hello",
WS_OVERLAPPED | WS_CAPTION | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
nullptr, nullptr, m_hInstance,
nullptr);
if(!m_hWnd)
{
OutputDebugString("Failed to create window\n");
return E_FAIL;
}
ShowWindow(m_hWnd, nCmdShow);
return S_OK;
}
LRESULT CALLBACK App::WndProc(
HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(msg)
{
case WM_CREATE:
{
} break;
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
} break;
case WM_DESTROY:
{
PostQuitMessage(0);
} break;
default:
{
DefWindowProc(hwnd, msg, wParam, lParam);
}
}
return 0;
}
and usage in main.cpp
#include "app.h"
#include "graphics.h"
// test comment
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
{
App app;
Graphics graphics(app.window());
if(FAILED(app.InitApp(hInstance, nCmdShow)));
return 0;
/*if(FAILED(graphics.InitGraphics()))
{
graphics.CleanUpDevice();
return 0;
}i*/
MSG msg = {0};
while(WM_QUIT != msg.message)
{
if(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//graphics.Render();
}
}
//graphics.CleanUpDevice();
return 0;
}
I have researched many of things like this, but nothing worked. I think I missed something very little...but I couldn't find anything. Please help out this pity noob coder....
WndProc does not return the value returned by DefWindowProc so when window receives WM_NCCREATE it will still return 0 indicating that window should not be created. Note that returning 0 from WM_CREATE is fine. Window proc should look like this:
LRESULT CALLBACK App::WndProc(
HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
LRESULT result{};
switch(msg)
{
case WM_CREATE:
{
result = 0;
} break;
case WM_PAINT:
{
PAINTSTRUCT ps;
hdc = BeginPaint(hwnd, &ps);
EndPaint(hwnd, &ps);
result = 0;
} break;
case WM_DESTROY:
{
PostQuitMessage(0);
result = 0;
} break;
default:
{
result = DefWindowProc(hwnd, msg, wParam, lParam);
}
}
return result;
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I'm trying to get a Windows/DirectX Input in my little program. I have tried it now for 2 days, but it is not working as expected.
It only recognizes the WM_KEYDOWN message if I asked for the WM_QUIT message before that. I can't find the solution to this weird problem. You can see the code below.
while(m_Running)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
MessageBox(NULL,"QUIT",NULL,MB_OK);
}
if(msg.message == WM_KEYDOWN)
{
MessageBox(NULL,"PRESS",NULL,MB_OK);
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(Update() == false)
{
m_Running = false;
}
}
You should move your handlers into a win proc:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_QUIT:
// ....
break;
case WM_KEYDOWN:
// ....
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
And change your loop to:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Also, when you create your window class:
myclass.lpfnWndProc = WndProc;
Following on from the link I posted, I've downloaded Visual Studio Express 2013 and compiled run the following, tested it works.
This contains window and class creation, a message loop, and a windows procedure to process messages.
// Trim fat from windows
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// Windows Procedure Message Handler
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// Switch message, condition that is met will execute*/
switch (message)
{
case WM_CLOSE:
MessageBox(NULL, "QUIT", NULL, MB_OK);
PostQuitMessage(0);
break;
case WM_KEYDOWN:
MessageBox(NULL, "PRESS", NULL, MB_OK);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
// Main function
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX windowClass; //window class
HWND hwnd; //window handle
MSG msg; //message
/* Fill out the window class structure*/
windowClass.cbSize = sizeof(WNDCLASSEX);
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc = WndProc;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hInstance = hInstance;
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
windowClass.lpszMenuName = NULL;
windowClass.lpszClassName = "MyClass";
windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
/* Register window class*/
if (!RegisterClassEx(&windowClass))
{
return 0;
}
/* Class registerd, so now create window*/
hwnd = CreateWindowEx(NULL, //extended style
"MyClass", //class name
"A Real Win App", //app name
WS_OVERLAPPEDWINDOW | //window style
WS_VISIBLE |
WS_SYSMENU,
100, 100, //x/y coords
400, 400, //width,height
NULL, //handle to parent
NULL, //handle to menu
hInstance, //application instance
NULL); //no extra parameter's
/* Check if window creation failed*/
if (!hwnd)
return 0;
bool done = false; //initialize loop condition variable
/* main message loop*/
while (!done)
{
PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE);
if (msg.message == WM_QUIT) //check for a quit message
{
done = true;
}
else
{
// Translate and dispatch to event queue
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}