C++ Win32 Background Image - c++

I have looked at some background drawing tutorials but I still can't draw my background; it's always white. My resources are already in the project. I have tried a few other ways by using paint instead but it still would not draw the background image.
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
HINSTANCE hInst;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND hProgress, hWndBottom;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
hInst = hInstance;
MSG msg = {0};
WNDCLASS wc = {0};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hbrBackground = CreatePatternBrush( LoadBitmap( hInstance, MAKEINTRESOURCE(IDB_BG) ));//(HBRUSH)(COLOR_BACKGROUND);
wc.lpszClassName = "Test";
if( !RegisterClass(&wc) )
return 1;
if( !CreateWindow(wc.lpszClassName,
"Tests",
WS_POPUPWINDOW|WS_VISIBLE, //WS_OVERLAPPEDWINDOW|WS_VISIBLE
1,1,200,250,0,0,hInstance,NULL))
return 2;
while( GetMessage( &msg, NULL, 0, 0 ) > 0 )
DispatchMessage( &msg );
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//Make TopMost
::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
INITCOMMONCONTROLSEX InitCtrlEx;
InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
InitCtrlEx.dwICC = ICC_PROGRESS_CLASS;
SendMessage(hProgress, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
switch(message)
{
case WM_CREATE:
{
hProgress = CreateWindowEx(0, PROGRESS_CLASS, NULL,
WS_CHILD | WS_VISIBLE | PBS_SMOOTH,
10, 190, 170, 10,
hWnd, NULL, hInst, NULL);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

If you're going to draw a bitmap for your background, you do not just set the background brush to the handle of your bitmap.
Instead, you set the background brush to NULL, and handle the WM_ERASEBKGND message. You respond to it by drawing your bitmap (e.g., with BitBlt or StretchBlt), then you return TRUE (or any other non-zero value) to tell DefWindowProc that the background has been erased, so it shouldn't try to erase it.
Note that if you're doing this in an MDI program, you need to do this in the MDI client window. With MDI, you have a parent window, a client window, and some number of MDI child windows. What looks like the background of the main window is really occupied by the MDI client window, so that's where you need to draw in your background.

Related

How to set chinese text into an edit field in Windows

I am new to using international languages in my win32 program in C++. I have a simple window created with an edit field inside. I want to set a chinese hardcoded text into the edit field. I am using SetWindowText but the output has only question marks and | character. What am I missing? My code file is pasted below. I have tried WM_SETTEXT but no luck.
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <strsafe.h>
#include <iostream>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
HWND edit = CreateWindowEx(0, L"Edit", L"", WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 200, 50, hwnd, NULL, hInstance, NULL);
SetWindowTextW(edit, L"銷售回扣");
//SendMessage(edit, WM_SETTEXT, 0, (LPARAM)(L"銷售回扣"));
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
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_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
// All painting occurs here, between BeginPaint and EndPaint.
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

The Bottom Border of a simple Windows Application keeps disappearing and reaapearing when resizing the window

Here's a simple Win32 Application that I copied from the official MSDN docs (link):
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = { };
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
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_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_DESKTOP+1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
The only difference is I used COLOR_DESKTOP instead of COLOR_WINDOW in FillRect() (this problem occurs in both the cases).
Whenever I resize the window, the bottom border keeps disappearing and then reappearing as I resize it further. Can anyone tell what's happening?
Here's GIF to show the bottom border disappearing when resizing:
I suggest you could try to enable DPI awareness: Property -> Manifest Tool ->Input and Output -> DPI Awareness.

Why is WM_NCCALSIZE is not called after the size of WinAPI control is changed?

I have a rich edit control who's size is changed after it is created.
I want to customize the control's appearance, so I need to recalculate the size of its client area each time the size of the control is changed. Idea was to change the size of the client area each time the component receives WM_NCCALCSIZE message, since MSDN documentation for WM_NCCALCSIZE states:
Sent when the size and position of a window's client area must be calculated. By processing this message, an application can control the content of the window's client area when the size or position of the window changes.
Problem is that the WM_NCCALCSIZE is not called after the size of the control is changed (It is called only once when the control is created).
This behavior is not specific to rich edit control. The same is true, e.g. for button controls. It also doesn't matter whether the size is changed before or after the component is shown on the screen.
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include <string>
#pragma comment(lib, "comctl32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK RichEditProc(HWND, UINT, WPARAM, LPARAM);
WNDPROC richEditOrigProc;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
LoadLibrary(TEXT("msftedit.dll"));
WNDCLASSEX mainwcex;
mainwcex.cbSize = sizeof(WNDCLASSEX);
mainwcex.style = CS_HREDRAW | CS_VREDRAW;
mainwcex.lpfnWndProc = WindowProc;
mainwcex.cbClsExtra = 0;
mainwcex.cbWndExtra = 0;
mainwcex.hInstance = hInstance;
mainwcex.hIcon = NULL;
mainwcex.hCursor = (HICON)LoadCursor(NULL, IDC_ARROW);
mainwcex.hbrBackground = GetSysColorBrush(COLOR_MENU);
mainwcex.lpszMenuName = NULL;
mainwcex.lpszClassName = "mainwindow";
mainwcex.hIconSm = NULL;
RegisterClassEx(&mainwcex);
HWND mainWindow = CreateWindowEx(
NULL,
"mainwindow",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
HWND richEditControl = CreateWindowEx(
NULL,
"RICHEDIT50W",
"Rich Edit",
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,
50,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
richEditOrigProc = (WNDPROC) SetWindowLongPtr(richEditControl, GWLP_WNDPROC, (LONG_PTR) RichEditProc);
// Changes the width of rich edit control from 100 px to 400 px.
SetWindowPos(richEditControl, NULL, 0, 0, 400, 25,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
ShowWindow(mainWindow, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(mainWindow, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK RichEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_NCCALCSIZE:
{
RECT newClientRect;
GetWindowRect(hWnd, &newClientRect);
MapWindowPoints(HWND_DESKTOP, GetParent(hWnd), reinterpret_cast<POINT*>(&newClientRect), 2);
InflateRect(&newClientRect, -3, -3);
int width = newClientRect.right - newClientRect.left;
int height = newClientRect.bottom - newClientRect.top;
if (wParam) {
NCCALCSIZE_PARAMS* ncParams = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
ncParams->rgrc[0].left = newClientRect.left;
ncParams->rgrc[0].top = newClientRect.top;
ncParams->rgrc[0].right = newClientRect.right;
ncParams->rgrc[0].bottom = newClientRect.bottom;
return WVR_HREDRAW;
}
return 0;
}
}
return CallWindowProc(richEditOrigProc, hWnd, uMsg, wParam, lParam);
}
In this example, it is evident that while the total size of the rich edit control is changed, it's client area is not recalculated and corresponds to its initial size.
What is the correct way to resize the client area of custom control, to reflect the change in its total size.
If you want to do things when a control is resized, you should be catching WM_SIZE, not WM_NCCALCSIZE.
The purpose of WM_NCCALCSIZE is to allow (for example) a captioned window to recalculate the size of its client area when the height of the caption bar changes. (Users can adjust this through the control panel, or at least they used to.) I would expect WM_NCCALCSIZE to be sent when the control is created though, bit of a mystery that.
WM_SIZE is fully documented at MSDN.
Also: I don't see you actually resizing that control anywhere in your code...
If you insist on using WM_NCCALCSIZE you should be able to force it with SetWindowPos by specifying the SWP_FRAMECHANGED flag.
WM_NCCALSIZE message was handled the wrong way. Instead of setting the coordinates of new client rectangle to the rgrc[0] rectangle of NCCALCSIZE_PARAMS, only increment/decrement relative to the control's total bounds should be set. Those increment/decrement values specify the size of the non-client area, i.e. the margins of the client area.
After the control's size is changed, the size of client area is automatically adjusted relative to the new control's bounds.
For example, this code sets the client area with top/bottom margins of 3 px and left/right margins of 50 px.
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include <string>
#pragma comment(lib, "comctl32.lib")
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK RichEditProc(HWND, UINT, WPARAM, LPARAM);
WNDPROC richEditOrigProc;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
LoadLibrary(TEXT("msftedit.dll"));
WNDCLASSEX mainwcex;
mainwcex.cbSize = sizeof(WNDCLASSEX);
mainwcex.style = CS_HREDRAW | CS_VREDRAW;
mainwcex.lpfnWndProc = WindowProc;
mainwcex.cbClsExtra = 0;
mainwcex.cbWndExtra = 0;
mainwcex.hInstance = hInstance;
mainwcex.hIcon = NULL;
mainwcex.hCursor = (HICON)LoadCursor(NULL, IDC_ARROW);
mainwcex.hbrBackground = GetSysColorBrush(COLOR_MENU);
mainwcex.lpszMenuName = NULL;
mainwcex.lpszClassName = "mainwindow";
mainwcex.hIconSm = NULL;
RegisterClassEx(&mainwcex);
HWND mainWindow = CreateWindowEx(
NULL,
"mainwindow",
NULL,
WS_OVERLAPPEDWINDOW,
100,
100,
600,
400,
NULL,
NULL,
hInstance,
NULL);
HWND richEditControl = CreateWindowEx(
NULL,
"RICHEDIT50W",
"Rich Edit",
WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP,
50,
50,
100,
25,
mainWindow,
NULL,
hInstance,
NULL);
richEditOrigProc = (WNDPROC) SetWindowLongPtr(richEditControl, GWLP_WNDPROC, (LONG_PTR) RichEditProc);
// Changes the width of rich edit control from 100 px to 400 px.
SetWindowPos(richEditControl, NULL, 0, 0, 400, 25,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
ShowWindow(mainWindow, nCmdShow);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
if (!IsDialogMessage(mainWindow, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK RichEditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_NCCALCSIZE:
{
if (wParam) {
NCCALCSIZE_PARAMS* ncParams = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
ncParams->rgrc[0].left += 50;
ncParams->rgrc[0].top += 3;
ncParams->rgrc[0].right -= 50;
ncParams->rgrc[0].bottom -= 3;
return WVR_HREDRAW;
}
return 0;
}
}
return CallWindowProc(richEditOrigProc, hWnd, uMsg, wParam, lParam);
}

Custom window proc in a separate file

I'm currently learning winapi, and would like to get some advice on how to set up a custom control using different window procedures.
Let's say I have 20 buttons. I want each button to respond differently when the mouse hovers over it. Say, an "exit" button draws a red rectangle when hovered, or blue when some other button is hovered.
So, I have set up a custom control procedure that handles mouse clicks, mouse hover, and such, and is stored in custom.cpp. In main.cpp, there is a MainProc() that "links/assigns" hwndButton to ButtonProc() using
CustomProcHandler = (WNDPROC)SetWindowLong(hwndButton, GWL_WNDPROC, (long)CustomProc)
main.h:
#include <windows.h>
#include <iostream>
using namespace std;
const char g_szClassName[] = "Applicaton";
static HWND hwnd, hwndButton;
static HINSTANCE hInst;
static WNDPROC buttonProcHandler;
LRESULT CALLBACK MainProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ButtonProc(HWND, UINT, WPARAM, LPARAM);
main.cpp:
#include "main.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR nCmdLine, int nCmdShow){
WNDCLASSEX wc;
MSG msg;
hInst = hInstance;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, 0);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = CreateSolidBrush(RGB(20, 20, 20));
wc.lpszMenuName = 0;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(hInst, 0);
RegisterClassEx(&wc);
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,
NULL, NULL, hInst, NULL);
ShowWindow(hwnd, 1);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch(msg){
case WM_CREATE:
button = CreateWindow("button", 0, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 10, 10, 32, 32, hwnd, 0, hInst, 0);
buttonProcHandler = (WNDPROC)SetWindowLong(hwndButton, GWL_WNDPROC, (long)ButtonProc);
break;
case WM_MOUSEMOVE:
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
custom.cpp:
#include "main.h"
LRESULT CALLBACK ButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch(msg){
case WM_CREATE:
break;
case WM_MOUSEMOVE:
break;
case WM_LBUTTONDOWN:
break;
default:
return CallWindowProc(buttonProcHandler, hwnd, msg, wParam, lParam);
}
return 0;
}
The problem is the button disappears... but when I move buttonProc() inside of main.cpp then everything works fine.
So, I am guessing I did something wrong when declaring global variables like static WNDPROC buttonProcHandler.
I know what I am doing is entirely wrong, and that there is a better way of doing it. I just don't know what that is.
Can anyone can help/teach me the standard way of creating custom procedures?

winapi display icon on the screen with mouseclick event

In WINAPI, I have seen a virus which displays an icon on the x-y of the mouse whenever a mouse click event occurs (the red one which has a white X inside). How do I show an icon like that whenever I click the mouse? I know how to hook mouse clicks with setwindowshookex. Is there a function like iconshow as I have shown below.
HHOOK msHOOK;
//getting the icon let's say from a rc file
HICON redIcon;
msHOOK = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, NULL, 0);
LRESULT CALLBACK mouseProc(int nCode, WPARAM wPar, LPARAM lPar){
IconShow(NULL, redIcon, xofMouse, yofMouse, 0);
MessageBox(NULL, "Icon showed", "Cap", 0);
return CallNextHookEx(NULL, nCode, wPar, lPar);
}
while(GetMessage(&msg, NULL, 0, 0) > 0){
TranslateMessage(&msg);
}
Thanks
UPDATE
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdParam, int iCmdShow){
HWND wnd;
MSG msg;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
wc.lpszMenuName = NULL;
wc.lpszClassName = "ClassName";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_LAYERED, "ClassName", "ss", NULL, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, NULL, NULL);
SetLayeredWindowAttributes(wnd, RGB(255, 255, 0), 20, LWA_COLORKEY);
ShowWindow(wnd, SW_SHOW);
while (GetMessage(&msg, NULL, 0, 0) > 0) {
TranslateMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_PAINT:
//stuff here
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
You would have to create your own always-on-top window to display the cursor.
It probably needs to be a layered window so you can use UpdateLayeredWindow() and a 32-bit RGBA bitmap to get every cursor looking correct.
If you are only using a specific cursor you control, and it does not have an alpha channel, you can save yourself some work by painting the image as-is onto your window in a WM_ERASEBKGND or WM_PAINT message handler, and then use SetLayeredWindowAttributes(..., LWA_COLORKEY, ...) to set the window's transparency color.