This question already has an answer here:
Is it possible to create a winapi window with only borders
(1 answer)
Closed 2 years ago.
I am dealing with win32. I have created a window. What I want is a transparent window for clicked area but nontransparent for border. Additionaly with no title bar. It should seem like an empty rectangle. When I add the following code I, my whole window becomes transparent (borders are also tranparent.)
SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 75, LWA_ALPHA);
SetWindowLong(hwnd, GWL_STYLE, 0);
The output of my code by adding the above code is like following:
When opacity value is 255:
When opacity value is 75
As you can see that the borders also transparent. How can I prevent becoming transparent border, but obtain transparent clicked area like a rectange?
Thanks...
It looks like you want to make part of the window transparent.For this, you need to create two windows to complete.
Use SetWindowRgn to create a window with a hole
Use the WS_EX_LAYERED and WS_EX_TRANSPARENT style to place
another transparent window in the hole.
Like this:
The whole code:
// Test_transparent.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "Test_transparent.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
// 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);
HWND hWnd;
HWND child;
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_TESTTRANSPARENT, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTTRANSPARENT));
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_TESTTRANSPARENT));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTTRANSPARENT);
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 = CreateWindowEx(0, szWindowClass, L" ", WS_POPUP, 100, 100, 800, 600, NULL, NULL, hInst, 0);
child = CreateWindowEx(WS_EX_LAYERED, szWindowClass, szTitle, WS_POPUP | WS_VISIBLE | WS_CHILD, 300, 300, 200, 200, hWnd, NULL, hInst, 0);
SetLayeredWindowAttributes(child, 0, 50, LWA_ALPHA);
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)
{
RECT rect;
RECT rc;
COLORREF brColor;
static HRGN hRgnWnd;
static HRGN hRgnWnd1;
static HBRUSH hBr;
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...
brColor = RGB(51, 143, 178);
hBr = CreateSolidBrush(brColor);
GetClientRect(hWnd, &rect);
rc.left = 200;
rc.top = 200;
rc.right = 400;
rc.bottom = 400;
hRgnWnd = CreateRectRgn(rect.left, rect.top, rect.right, rect.bottom);
hRgnWnd1 = CreateRectRgn(rc.left, rc.top, rc.right, rc.bottom);
CombineRgn(hRgnWnd1, hRgnWnd1, hRgnWnd, RGN_XOR);
SetWindowRgn(hWnd, hRgnWnd1, true);
FillRect(hdc, &rect, hBr);
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;
}
To get a borderless window, you need to comment the MENU code in the .rc file.
.rc cpp
//Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE resource.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_TESTTRANSPARENT ICON "Test_transparent.ico"
IDI_SMALL ICON "small.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
//
//IDC_TESTTRANSPARENT MENU
//BEGIN
// POPUP "&File"
// BEGIN
// MENUITEM "E&xit", IDM_EXIT
// END
// POPUP "&Help"
// BEGIN
// MENUITEM "&About ...", IDM_ABOUT
// END
//END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDC_TESTTRANSPARENT ACCELERATORS
BEGIN
"?", IDM_ABOUT, ASCII, ALT
"/", IDM_ABOUT, ASCII, ALT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Test_transparent"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20
LTEXT "Test_transparent, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
LTEXT "Copyright (c) 2020",IDC_STATIC,42,26,114,8
DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 163
TOPMARGIN, 7
BOTTOMMARGIN, 55
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#ifndef APSTUDIO_INVOKED\r\n"
"#include ""targetver.h""\r\n"
"#endif\r\n"
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDC_TESTTRANSPARENT "TESTTRANSPARENT"
IDS_APP_TITLE "Test_transparent"
END
#endif
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
Related
I am writing an app in C++ with the Win32 API. I first noticed that the rendered text with DrawTextLayout() was very fuzzy, so I added the following line:
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
At first, this seemed to do the trick: the text looked much crisper, and more of what I would expect from a Windows app.
However, when I resized the window (by dragging the bottom corner), I noticed that the text I drew was distorted.
How could I keep the crispness of using DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2, but also keep the text from becoming stretched?
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <dwrite.h>
#include <d2d1.h>
#define IDS_APP_TITLE 103
#define IDR_MAINFRAME 128
#define IDD_PRACTICE_DIALOG 102
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_PRACTICE 107
#define IDI_SMALL 108
#define IDC_PRACTICE 109
#define IDC_MYICON 2
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
#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
ID2D1Factory* m_pD2DFactory;
ID2D1HwndRenderTarget* m_pRenderTarget;
ID2D1SolidColorBrush* m_pBlackBrush;
IDWriteFactory* writeFactory;
IDWriteTextFormat* writeTextFormat;
IDWriteTextLayout* writeTextLayout;
RECT rc;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
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_PRACTICE));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PRACTICE);
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, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr);
//create device independent resources
{
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
// Create a Direct2D factory.
D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&m_pD2DFactory
);
DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&writeFactory)
);
}
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_PRACTICE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PRACTICE));
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;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
//create device dependent resources
{
HRESULT hr = S_OK;
if (!m_pRenderTarget) {
GetClientRect(hWnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
// Create a Direct2D render target
hr = m_pD2DFactory->CreateHwndRenderTarget(D2D1::RenderTargetProperties(), D2D1::HwndRenderTargetProperties(hWnd, size), &m_pRenderTarget);
if (SUCCEEDED(hr))
{
// Create a black brush
hr = m_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &m_pBlackBrush);
}
}
}
//render text
{
writeFactory->CreateTextFormat(
L"Times New Roman",
NULL,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
14.0f,
L"EN-US",
&writeTextFormat
);
writeFactory->CreateTextLayout(
L"String", // The string to be laid out and formatted.
6, // The length of the string.
writeTextFormat, // The text format to apply to the string (contains font information, etc).
200, // The length of the layout box.
500, // The width of the layout box.
&writeTextLayout // The IDWriteTextLayout interface pointer.
);
}
m_pRenderTarget->BeginDraw();
m_pRenderTarget->SetTransform(D2D1::IdentityMatrix());
m_pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::White));
m_pRenderTarget->DrawTextLayout(D2D1::Point2F(0, 0), writeTextLayout, m_pBlackBrush);
m_pRenderTarget->EndDraw();
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
I apologize that this is a substantial amount of code; however, to be able to be completely run, I had to include this much.
Although setting dpi-awareness is a critical step to avoid bluriness on high-res monitors (when dpi is not 100%), your issue with the text getting stretched on a window resize is a separate issue.
This is simply a DirectX (DirectWrite) surface issue. I only have limited experience with DirectWrite, but the fix for this is very obvious. Like D3D, the DirectWrite surface stretches across the size of the window, but it's not directly aware of the window size change until you tell it.
Potentially two very easy fixes:
In your WndProc function, pass the new size to the m_pRenderTarget thing when the size changes. Catch WM_SIZE:
case WM_SIZE:
{
if (m_pRenderTarget)
{
GetClientRect(hWnd, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
m_pRenderTarget->Resize(size);
}
break;
}
Alternatively, since your WM_PAINT code would re-create the thing anyway if it's null:
case WM_SIZE:
{
if (m_pRenderTarget)
{
m_pRenderTarget->Release();
m_pRenderTarget = nullptr;
}
break;
}
One other minor fix. Invoke SetProcessDpiAwarenessContext before you call CreateWindow. Very early in WinMain before you start doing anything else. Or use the application manifest file to set it.
I have a button which is subclassed and I would like it to display a bitmap with a transparent background. Upon searching the internet, I found that you have to do it with the function AlphaBlend( I tried this but that didn't work either). I also saw this bitmap transparency in Visual Studio 2013 C++ thread and I tried the steps but I couldn't do it. I would be fine with either GDI or GDI+ just as long as i can get button with a transparent background image on it.
Example:
Here is my code—— I know it's messy but please bare with it as I was trying a lot of things to try and make it work (there was a lot of copying and pasting)
Update : Here is the code again but trimmed without all the fat and yes I did try WS_EX_LAYERED on both the windows.
// CustomButton2.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "CustomButton2.h"
#include <commctrl.h>
#include <gdiplus.h>
#include <system_error>
#include "SkinClass/skin.h"
#define MAX_LOADSTRING 100
#define CRAPPY 567
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' " "version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
const char g_szClassName[] = "MyClassName";
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
void RegisterClass1(HINSTANCE);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
/// Turn given window into a layered window and load a bitmap from given resource ID
/// into it.
/// The window will be resized to fit the bitmap.
/// Bitmap must be 32bpp, top-down row order, premultiplied alpha.
///
/// \note For child windows, this requires Win 8 or newer OS
/// (and "supportedOS" element for Win 8 in application manifest)
///
/// \exception Throws std::system_error in case of any error.
void SetLayeredWindowFromBitmapResource(
HWND hwnd, UINT bitmapResourceId, HINSTANCE hInstance = nullptr)
{
// Enable "layered" mode for the child window. This enables full alpha channel
// transparency.
// GetWindowLong() won't reset the last error in case of success.
// As we can't judge from the return value of GetWindowLong() alone if
// the function was successful (0 may be returned even in case of
// success), we must reset the last error to reliably detect errors.
::SetLastError(0);
DWORD exStyle = ::GetWindowLong(hwnd, GWL_EXSTYLE);
if (!exStyle)
{
// NOTE: Call GetLastError() IMMEDIATELY when a function's return value
// indicates failure and it is documented that said function supports
// GetLastError().
// ANY other code (be it your own or library code) before the next line
// must be avoided as it may invalidate the last error value.
if (DWORD err = ::GetLastError())
throw std::system_error(static_cast<int>(err),
std::system_category(),
"SetLayeredWindowFromBitmapResource: Could not get extended window style");
}
// SetWindowLong() won't reset the last error in case of success.
// As we can't judge from the return value of GetWindowLong() alone if
// the function was successful (0 may be returned even in case of
// success), we must reset the last error to reliably detect errors.
::SetLastError(0);
if (!::SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED))
{
if (DWORD err = ::GetLastError())
throw std::system_error(static_cast<int>(err),
std::system_category(),
"SetLayeredWindowFromBitmapResource: Could not set extended window style");
}
// Use RAII ( https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization )
// to cleanup resources even in case of exceptions.
// This greatly simplifies the code because now we don't have to manually cleanup the
// resources at every location in the code where we throw an exception.
struct Resources {
HBITMAP hImage = nullptr;
HGDIOBJ hOldImage = nullptr;
HDC hMemDC = nullptr;
// This destructor will be automatically called before the function
// SetLayeredWindowFromBitmapResource() returns aswell as any locations
// in the code where the "throw" keyword is used to throw an exception.
~Resources()
{
if (hMemDC)
{
if (hOldImage)
::SelectObject(hMemDC, hOldImage);
::DeleteDC(hMemDC);
}
if (hImage)
::DeleteObject(hImage);
}
} res;
// Make it possible to use nullptr as an argument for the hInstance parameter of
// this function. This means we will load the resources from the current executable
// (instead of another DLL).
if (!hInstance)
hInstance = ::GetModuleHandle(nullptr);
// Load bitmap with alpha channel from resource.
// Flag LR_CREATEDIBSECTION is required to create a device-independent bitmap that
// preserves the alpha channel.
res.hImage = reinterpret_cast<HBITMAP>(::LoadImage(
hInstance, MAKEINTRESOURCE(bitmapResourceId), IMAGE_BITMAP,
0, 0, LR_CREATEDIBSECTION));
if (!res.hImage)
{
DWORD err = ::GetLastError();
throw std::system_error(static_cast<int>(err),
std::system_category(),
"SetLayeredWindowFromBitmapResource: Could not load bitmap resource");
}
// Get bitmap information (width, height, etc.)
BITMAP imgInfo{ 0 };
if (!::GetObject(res.hImage, sizeof(imgInfo), &imgInfo))
{
DWORD err = ::GetLastError();
throw std::system_error(static_cast<int>(err),
std::system_category(),
"SetLayeredWindowFromBitmapResource: Could not get bitmap information");
}
if (imgInfo.bmBitsPixel != 32 || imgInfo.bmPlanes != 1)
{
// Use a constant error value here because this is our own error condition.
// Of course GetLastError() wouldn't return anything useful in this case.
DWORD err = ERROR_INVALID_DATA;
throw std::system_error(err, std::system_category(),
"SetLayeredWindowFromBitmapResource: bitmap must be 32 bpp, single plane");
}
// Create a memory DC that will be associated with the image.
// UpdateLayeredWindow() can't use image directly, it must be in a memory DC.
res.hMemDC = ::CreateCompatibleDC(nullptr);
if (!res.hMemDC)
{
DWORD err = ::GetLastError();
throw std::system_error(static_cast<int>(err),
std::system_category(),
"SetLayeredWindowFromBitmapResource: Could not create memory DC");
}
res.hOldImage = ::SelectObject(res.hMemDC, res.hImage);
if (!res.hOldImage)
{
DWORD err = ::GetLastError();
throw std::system_error(static_cast<int>(err),
std::system_category(),
"SetLayeredWindowFromBitmapResource: Could not select bitmap into memory DC");
}
// Assign the image to the child window, making it transparent.
SIZE size{ imgInfo.bmWidth, imgInfo.bmHeight };
POINT ptSrc{ 0, 0 };
BLENDFUNCTION blend{ AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
if (!::UpdateLayeredWindow(hwnd, nullptr, nullptr, &size, res.hMemDC, &ptSrc,
0, &blend, ULW_ALPHA))
{
DWORD err = ::GetLastError();
throw std::system_error(static_cast<int>(err),
std::system_category(),
"SetLayeredWindowFromBitmapResource: Could not update layered window");
}
// Destructor of res object will cleanup resources here!
}
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.
RegisterClass1(hInstance);
HWND hWnd = CreateWindowExA(WS_EX_LAYERED, g_szClassName, "Scenes", WS_OVERLAPPEDWINDOW | WS_EX_LAYERED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
hInstance, NULL);
HWND hButton = CreateWindow(TEXT("BUTTON"), TEXT("START EDITING!"), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW | WS_EX_LAYERED, 1, 1,228, 228,
hWnd, (HMENU)CRAPPY, NULL, NULL);
//SetLayeredWindowFromBitmapResource(hButton, ID_THECIRCLE, hInstance);
SetLayeredWindowAttributes(hWnd, 0, 249, LWA_ALPHA);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
SetLayeredWindowFromBitmapResource(hButton, ID_THECIRCLE);
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//
// FUNCTION: RegisterClass1()
//
// PURPOSE: Registers the class
//
// COMMENTS:
//
//
//
//
void RegisterClass1(HINSTANCE hInstance) {
WNDCLASSEXA wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
//wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hbrBackground = CreateSolidBrush(RGB(255, 0, 0));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = g_szClassName;
wc.lpszMenuName = "MENU";
wc.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
}
}
//
// 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:
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;
}
Starting from Window 8, WS_EX_LAYERED can be used for child controls.
Method: A manifest file is required to specify at least Window 8 compatibility (sub-layering is only supported from Window 8).
Refer: Targeting your application for Windows
Code Sample: (error check has been removed)
// Test_CustomButton.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "Test_CustomButton.h"
#include <commctrl.h>
#include <system_error>
#pragma comment (lib,"Comctl32.lib")
#define MAX_LOADSTRING 100
#define IDC_OWNERDRAWBUTTON 101
#define CRAPPY 567
// 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);
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
void SetLayeredWindowFromBitmapResource(
HWND hwnd, UINT bitmapResourceId, HINSTANCE hInstance = nullptr)
{
DWORD exStyle = ::GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
struct Resources {
HBITMAP hImage = nullptr;
HGDIOBJ hOldImage = nullptr;
HDC hMemDC = nullptr;
~Resources()
{
if (hMemDC)
{
if (hOldImage)
::SelectObject(hMemDC, hOldImage);
::DeleteDC(hMemDC);
}
if (hImage)
::DeleteObject(hImage);
}
} res;
if (!hInstance)
hInstance = ::GetModuleHandle(nullptr);
res.hImage = reinterpret_cast<HBITMAP>(::LoadImage(
hInstance, MAKEINTRESOURCE(bitmapResourceId), IMAGE_BITMAP,
0, 0, LR_CREATEDIBSECTION));
BITMAP imgInfo{ 0 };
GetObject(res.hImage, sizeof(imgInfo), &imgInfo);
res.hMemDC = ::CreateCompatibleDC(nullptr);
res.hOldImage = ::SelectObject(res.hMemDC, res.hImage);
// Assign the image to the child window, making it transparent.
SIZE size{ imgInfo.bmWidth, imgInfo.bmHeight };
POINT ptSrc{ 0, 0 };
BLENDFUNCTION blend{ AC_SRC_OVER, 0, 200, AC_SRC_ALPHA };
UpdateLayeredWindow(hwnd, nullptr, nullptr, &size, res.hMemDC, &ptSrc,
0, &blend, ULW_ALPHA);
// Destructor of res object will cleanup resources here!
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_TESTCUSTOMBUTTON, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTCUSTOMBUTTON));
MSG msg;
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_TESTCUSTOMBUTTON));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTCUSTOMBUTTON);
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);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HWND hButton = CreateWindowEx(0, L"button", NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 150, 50, 80, 80, hWnd, (HMENU)IDC_OWNERDRAWBUTTON, hInst, NULL);
SetWindowSubclass(hButton, &OwnerDrawButtonProc, IDC_OWNERDRAWBUTTON, 0);
}
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);
// Used be test
HPEN hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
SelectObject(hdc, hPen);
MoveToEx(hdc, 150, 150, NULL);
LineTo(hdc, 200, 60);
LineTo(hdc, 250, 150);
LineTo(hdc, 150, 150);
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;
}
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_PAINT:
{
RECT rc;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
SetLayeredWindowFromBitmapResource(hWnd, IDB_BITMAP1);
EndPaint(hWnd, &ps);
return 0;
}
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, &OwnerDrawButtonProc, 1);
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Debug:
Note:
When I tested, I found that the following conditions need to be met:
The image to load must be a 32 bpp, top-down bitmap with
premultiplied alpha channel.
Here is my 32 bpp image for your test.
As I said at the beginning, you need to add a manifest file, you can
create a .manifest file yourself. Then add it in the compiler.
You only need to add the WS_EX_LAYERED style to the child control,
because your requirement is to make the buttons transparent.
In my case the code that was provided didn't work because it was throwing an exception and I didn't add the manifest file properly. I would like to note some things:
Bitmap Images made with gimp do not work; use what was suggested in the thread that I linked in my question and that would be PixelFormer. In Pixel Former go "file", then "Import" and choose your file(in my case it was transparent png of a circle). Next go to "export" and choose bitmap bmp (windows bitmap it will say). Once you do that, already A8:R8:G8:B8 (32bpp) will be selected and you have to next check the last two boxes "Premultiplied Alpha" and "Top-down row order". What has to be said is that image does indeed have an alpha channel and it's transparent. Don't be fooled in opening up in paint and you see a black background and you think the transparency isn't there—— it's there the transparency works... If you open it up it in photoshop (i think) or a sophisiticated image editing program you will see a transparent background in your image.
manifest.xml
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
Copy the above and save it as manifest.xml
The other thing that I would like to note is adding a manifest entry file: in my case I had to add it to C:\Users\Rubel\source\repos\CustomButton2\CustomButton2 so whoever is looking at this in the future, replace that with your directory of your project;for example, C:\Users\blah\source\repos\blah\blah (the blahs with the name of your stuff). Paste your manifest file there (in the directory).
You then have to add it to visual studio. You do this by right clicking in your project in the solution explorer (in my case it was CustomButton2 ) and go to "Manifest Tool" in "Input and Output". In here type in "Additional Manifest Files" the path of your manifest file (in my case it was manifest.xml but if you were following along, then this should be the case as well for your path) and click ok.
That is it, if you used the code ( Strive Sun - MSFT ) that was given it should work.
Here is my final code if anyone was interested:
// CustomButton2.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "CustomButton2.h"
#include <commctrl.h>
#include <gdiplus.h>
#include <system_error>
#define MAX_LOADSTRING 100
#define CRAPPY 567
#define IDC_OWNERDRAWBUTTON 101
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' " "version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
const char g_szClassName[] = "MyClassName";
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
void RegisterClass1(HINSTANCE);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
void SetLayeredWindowFromBitmapResource(
HWND hwnd, UINT bitmapResourceId, HINSTANCE hInstance = nullptr)
{
DWORD exStyle = ::GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
struct Resources {
HBITMAP hImage = nullptr;
HGDIOBJ hOldImage = nullptr;
HDC hMemDC = nullptr;
~Resources()
{
if (hMemDC)
{
if (hOldImage)
::SelectObject(hMemDC, hOldImage);
::DeleteDC(hMemDC);
}
if (hImage)
::DeleteObject(hImage);
}
} res;
if (!hInstance)
hInstance = ::GetModuleHandle(nullptr);
res.hImage = reinterpret_cast<HBITMAP>(::LoadImage(
hInstance, MAKEINTRESOURCE(bitmapResourceId), IMAGE_BITMAP,
0, 0, LR_CREATEDIBSECTION));
BITMAP imgInfo{ 0 };
GetObject(res.hImage, sizeof(imgInfo), &imgInfo);
res.hMemDC = ::CreateCompatibleDC(nullptr);
res.hOldImage = ::SelectObject(res.hMemDC, res.hImage);
// Assign the image to the child window, making it transparent.
SIZE size{ imgInfo.bmWidth, imgInfo.bmHeight };
POINT ptSrc{ 0, 0 };
BLENDFUNCTION blend{ AC_SRC_OVER, 0, 200, AC_SRC_ALPHA };
UpdateLayeredWindow(hwnd, nullptr, nullptr, &size, res.hMemDC, &ptSrc,
0, &blend, ULW_ALPHA);
// Destructor of res object will cleanup resources here!
}
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.
RegisterClass1(hInstance);
HWND hWnd = CreateWindowExA(WS_EX_LAYERED, g_szClassName, "Scenes", WS_OVERLAPPEDWINDOW | WS_EX_LAYERED, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL,
hInstance, NULL);
HWND hButton = CreateWindow(TEXT("BUTTON"), TEXT("START EDITING!"), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW | WS_EX_LAYERED, 1, 1,228, 228,
hWnd, (HMENU)CRAPPY, NULL, NULL);
SetWindowSubclass(hButton, &OwnerDrawButtonProc, IDC_OWNERDRAWBUTTON, 0);
//SetLayeredWindowFromBitmapResource(hButton, ID_THECIRCLE, hInstance);
SetLayeredWindowAttributes(hWnd, 0, 249, LWA_ALPHA);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
//SetLayeredWindowFromBitmapResource(hButton, ID_THECIRCLE);
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
//
// FUNCTION: RegisterClass1()
//
// PURPOSE: Registers the class
//
// COMMENTS:
//
//
//
//
void RegisterClass1(HINSTANCE hInstance) {
WNDCLASSEXA wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
//wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hbrBackground = CreateSolidBrush(RGB(255, 0, 0));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = g_szClassName;
wc.lpszMenuName = "MENU";
wc.style = CS_HREDRAW | CS_VREDRAW;
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
}
}
//
// 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:
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;
}
LRESULT CALLBACK OwnerDrawButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
case WM_PAINT:
{
RECT rc;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
SetLayeredWindowFromBitmapResource(hWnd, ID_THECIRCLE);
EndPaint(hWnd, &ps);
return 0;
}
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, &OwnerDrawButtonProc, 1);
break;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Application running :
I know this was verbose but I wanted it to be easy for whoever is encountering this so that they know how to do it.
I'm relatively new to programming and I wanted to try and see how to make a basic Windows Desktop Application in Visual Studio 2019. Since I added code for a button the C2360 and C2361 errors keep popping up and I don't know what in the code is causing it.
I've looked up solutions such as putting {} around the block of code and those don't seem to work.
// HelloWindowsDesktop.cpp
// compile with: /D_UNICODE /DUNICODE /DWIN32 /D_WINDOWS /c
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
// Global variables
// The main window class name.
static TCHAR szWindowClass[] = _T("DesktopApp");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("WIndows Application test");
HINSTANCE hInst;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM );
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
{
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, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// Store instance handle in our global variable
hInst = hInstance;
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
500, 100,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// 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)
{
PAINTSTRUCT ps;
HDC hdc;
TCHAR greeting[] = _T("Hey Guys, this is my first Visual Studio desktop application, it has 158 lines of code!!!!!");
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, Windows desktop!"
// in the top left corner.
TextOut(hdc,
5, 5,
greeting, _tcslen(greeting));
HWND hwndButton = CreateWindow(
L"BUTTON", // Predefined class; Unicode assumed
L"OK", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
10, // x position
10, // y position
100, // Button width
100, // Button height
hWnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
// End application-specific layout section.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
The expected output is of a new window with some text and a button to appear in the top left-hand corner but only the text appears. The following errors appear:
Error C2360, initialization of 'hwndButton' is skipped by 'case' label, line 149
Error C2361, initialization of 'hwndButton' is skipped by 'default' label, line 152
Add the declaration of HWND hwndButton, move CreateWindow to WM_CREATE.Besides, move the TCHAR greeting[] out of WndProc()
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
// Global variables
// The main window class name.
static TCHAR szWindowClass[] = _T("DesktopApp");
// The string that appears in the application's title bar.
static TCHAR szTitle[] = _T("WIndows Application test");
TCHAR greeting[] = _T("Hey Guys, this is my first Visual Studio desktop application, it has 158 lines of code!!!!!");
HINSTANCE hInst;
HWND hwndButton; // add here
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
{
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, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// Store instance handle in our global variable
hInst = hInstance;
// The parameters to CreateWindow explained:
// szWindowClass: the name of the application
// szTitle: the text that appears in the title bar
// WS_OVERLAPPEDWINDOW: the type of window to create
// CW_USEDEFAULT, CW_USEDEFAULT: initial position (x, y)
// 500, 100: initial size (width, length)
// NULL: the parent of this window
// NULL: this application does not have a menu bar
// hInstance: the first parameter from WinMain
// NULL: not used in this application
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
600, 400,
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Call to CreateWindow failed!"),
_T("Windows Desktop Guided Tour"),
NULL);
return 1;
}
// The parameters to ShowWindow explained:
// hWnd: the value returned from CreateWindow
// nCmdShow: the fourth parameter from WinMain
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// 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)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
hwndButton = CreateWindowW(
L"BUTTON", // Predefined class; Unicode assumed
L"OK", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
10, // x position
10, // y position
100, // Button width
100, // Button height
hWnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
NULL); // Pointer not needed.
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// Here your application is laid out.
// For this introduction, we just print out "Hello, Windows desktop!"
// in the top left corner.
TextOut(hdc, 5, 5, greeting, _tcslen(greeting));
// End application-specific layout section.
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
I am new with programming Win32 applications. I have programmed a text box where the user can enter text. The problem is that I don't know how to get the input of the box into a string, which is necessary to process the input. For testing purposes, I tried to give out the entered text through the output text box, which I had to program anyway.
Googling, I found out that GetWindowTextA(hInput, input, length); should do the trick. However, I am not sure how to get the input into a variable using this method.
So, my question is, how do I get a text, entered by a user into a text box, into a string?
In case this does matter: I am not using the free version of Visual Studio, as I have free access to Microsoft software through my university. And at the moment I am using Visual Studio 2015 Ultimate Preview anyway. To answer the question in advance, this is NO homework or other work for my university, for a job or anything commercially. I have taught myself C++, which has become my favorite programming language, and I want to be able to program graphical interfaces with it.
Here is Visual Studio's standard code with some modifications, most notably the addition of two text boxes and a button (which does nothing at the moment and is of no importance for this question):
Includes, globals, forward declarations
#include "stdafx.h"
#include "WilliTeX.h"
#include <iostream>;
using namespace std;
#define MAX_LOADSTRING 100
//custom defines
#define TEXT_INPUT_BOX 1
#define TEXT_OUTPUT_BOX 2
#define BUTTON 3
HWND hInput;
HWND hOutput;
HWND hButton;
int length;
LPSTR input;
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR 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);
_tWinMain
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
HACCEL hAccelTable;
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WILLITEX, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WILLITEX));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
MyRegisterClass
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
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_WILLITEX));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WILLITEX);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
Rest of Code
//
// 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_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 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;
switch (message)
{
case WM_CREATE:
{
//This is the input box, where the user enters the text
hInput = CreateWindowExA(WS_EX_CLIENTEDGE,
"EDIT",
"",
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
50, //moving left/right the box
10, //moving up/down the box
1300, //length
350, //height
hWnd,
(HMENU)TEXT_INPUT_BOX,
GetModuleHandle(NULL),
NULL);
//This is the output text box, that will display the convertion
hInput = CreateWindowExA(WS_EX_CLIENTEDGE,
"Edit",
"test",
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
50, //moving left/right the box
200, //moving up/down the box
1300, //length
450, //height
hWnd,
(HMENU)TEXT_INPUT_BOX,
GetModuleHandle(NULL),
NULL);
hButton = CreateWindowExA(NULL,
"BUTTON",
"OK",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
3, //moving left/right
10, //moving up/down
48, //length
50, //height
hWnd,
(HMENU) BUTTON,
GetModuleHandle(NULL),
NULL);
break;
}
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
switch (LOWORD(wParam)) {
//refreshing the output box whenever the user is giving an input
case TEXT_INPUT_BOX:
{
length = GetWindowTextLengthA(hInput);
GetWindowTextA(hInput, input, length);
hInput = CreateWindowExA(WS_EX_CLIENTEDGE,
"Edit",
input,
WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
50, //moving left/right the box
200, //moving up/down the box
1300, //length
450, //height
hWnd,
(HMENU)TEXT_INPUT_BOX,
GetModuleHandle(NULL),
NULL);
break;
}
case BUTTON:
{
break;
}
}
// 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);
// TODO: Add any drawing code 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;
}
P.S. I am aware that using namespace std; is bad coding practice but for this learning program I don't really care.
You seem to be creating the input text box (again) when you get a message from it. That doesn't make sense. ANd your GetWindowTextA call is using a variable 'input' that you have not defined. Allocate a character array for that variable.
I have created this simple window with Visual Studio 2010:
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <tchar.h>
#define MAX_LOADSTRING 100
#define IDS_APP_TITLE 103
#define IDR_MAINFRAME 128
#define IDD_PROVIAMO_DIALOG 102
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_PROVIAMO 107
#define IDI_SMALL 108
#define IDC_PROVIAMO 109
#define IDC_MYICON 2
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 130
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR 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 _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_PROVIAMO, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PROVIAMO));
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
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_PROVIAMO));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PROVIAMO);
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_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 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;
RECT rect ;
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);
MessageBox (NULL,TEXT("Hello emy"), TEXT ("HelloMsg"), 0x00000006L | MB_ICONASTERISK);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
GetClientRect (hWnd, &rect) ;
DrawText (hdc, TEXT ("Ciao Emiliano :)"), -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER) ;
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;
}
If I compile it with Visual Studio then works but if I compile it with Code::Block and the execute the compiled file then the window doesn't appears but appears a Command Prompt with this:
"Process Returned 0 (0x0) execution time 0,266s
Press any key to continue"
Why ?
On Windows, there is a difference between a console application and a windows application application type.
Try specify an application type to windows application in your Code::Block project.
Is there a .rc resource file included with that simple test project? If the window class registration has references to resources, such as strings for instance, that doesn't actually exist anywhere in the executable then that could cause problems.
I'm going to guess your window creation is silently failing somewhere probably due to a resource not being available in the compiled application. It doesn't look like the code has thorough error checking on the return values so you might need to step it through a debugger to see what's happening.
Check if a resource file's suppose to go with it. Include it into Codeblocks so it actually gets compiled in and try running the app again.
Edit: On another note, help mankind by supporting this proposal :)