I have a task to create a program which displays a list of descriptors of all windows in the system. I am getting this output:
Maybe it's wrong encoding?
Here's my code:
#include <windows.h>
ATOM RegMyWindowClass(HINSTANCE, LPCTSTR);
HWND hListBox;
HINSTANCE hin;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
WCHAR str[255];
if (GetWindowTextW(hwnd, str, 255)) {
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER)))
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
return 1;
}
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
MessageBox(hWnd, TEXT("Вы кликнули!"), TEXT("событие"), 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hListBox = CreateWindow("LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
LPCTSTR lpzClass = TEXT("My Window Class!");
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
RECT screen_rect;
GetWindowRect(GetDesktopWindow(), &screen_rect);
int x = screen_rect.right / 2 - 200;
int y = screen_rect.bottom / 2 - 200;
HWND hWnd = CreateWindow(lpzClass, TEXT("Window"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
EnumWindows(&EnumWindowsProc, 0);
if (!hWnd) return 2;
MSG msg = { 0 };
int iGetOk = 0;
while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (iGetOk == -1) return 3;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName)
{
WNDCLASS wcWindowClass = { 0 };
wcWindowClass.lpfnWndProc = (WNDPROC)WndProc;
wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
wcWindowClass.hInstance = hInst;
wcWindowClass.lpszClassName = lpzClassName;
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClass(&wcWindowClass);
}
Any ideas how to fix this?
The problem is that you are compiling your project for ANSI, where TCHAR is an alias for CHAR, and are thus creating an ANSI-based ListBox, but you are sending Unicode strings to it. That is why you are seeing garbage in the output. You need to send ANSI strings to the ListBox, eg:
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER)))
CHAR str[255] = {};
if (GetWindowTextA(hwnd, str, 255)) {
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
}
return TRUE;
}
Alternatively:
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
CHAR str[255] = {};
if (IsWindowUnicode(hwnd)) {
WCHAR wstr[255] = {};
int len = GetWindowTextW(hwnd, wstr, 255);
if (len) {
len = WideCharToMultiByte(CP_ACP, 0, wstr, len+1, str, 255, NULL, NULL);
}
if (!len) {
return TRUE;
}
}
else if (!GetWindowTextA(hwnd, str, 255)) {
return TRUE;
}
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
return TRUE;
}
That being said, you are mixing ANSI, Unicode, and TCHAR APIs. You need to pick 1 API style and stick with it for everything, don't mix them (unless you ABSOLUTELY have to).
Since the majority of the code you have shown is already using TCHAR, then you can use TCHAR for everything (though, you really shouldn't, since TCHAR is meant for backwards compatibility with Win9x/ME which nobody uses anymore, and was intended only to help people migrate their code to Unicode. Modern code should not be using TCHAR at all):
#include <windows.h>
ATOM RegMyWindowClass(HINSTANCE, LPCTSTR);
HWND hListBox;
HINSTANCE hin;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
TCHAR str[255];
if (GetWindowText(hwnd, str, 255)) {
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
}
return TRUE;
}
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
// this is one case where it doesn't make sense to use TCHAR
MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hListBox = CreateWindow(TEXT("LISTBOX"), TEXT(""), WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
LPCTSTR lpzClass = TEXT("My Window Class!");
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
RECT screen_rect;
GetWindowRect(GetDesktopWindow(), &screen_rect);
int x = screen_rect.right / 2 - 200;
int y = screen_rect.bottom / 2 - 200;
HWND hWnd = CreateWindow(lpzClass, TEXT("Window"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
EnumWindows(&EnumWindowsProc, 0);
if (!hWnd) return 2;
MSG msg = { 0 };
int iGetOk = 0;
while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (iGetOk == -1) return 3;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName)
{
WNDCLASS wcWindowClass = { 0 };
wcWindowClass.lpfnWndProc = &WndProc;
wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
wcWindowClass.hInstance = hInst;
wcWindowClass.lpszClassName = lpzClassName;
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClass(&wcWindowClass);
}
Otherise, use Unicode for everything:
#include <windows.h>
ATOM RegMyWindowClass(HINSTANCE, LPCWSTR);
HWND hListBox;
HINSTANCE hin;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
WCHAR str[255];
if (GetWindowTextW(hwnd, str, 255)) {
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
}
return TRUE;
}
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hListBox = CreateWindowW(L"LISTBOX", L"", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
LPCWSTR lpzClass = L"My Window Class!";
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
RECT screen_rect;
GetWindowRect(GetDesktopWindow(), &screen_rect);
int x = screen_rect.right / 2 - 200;
int y = screen_rect.bottom / 2 - 200;
HWND hWnd = CreateWindowW(lpzClass, L"Window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
EnumWindows(&EnumWindowsProc, 0);
if (!hWnd) return 2;
MSG msg = { 0 };
int iGetOk = 0;
while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (iGetOk == -1) return 3;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM RegMyWindowClass(HINSTANCE hInst, LPCWSTR lpzClassName)
{
WNDCLASSW wcWindowClass = { 0 };
wcWindowClass.lpfnWndProc = &WndProc;
wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
wcWindowClass.hInstance = hInst;
wcWindowClass.lpszClassName = lpzClassName;
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClassW(&wcWindowClass);
}
Or, stick with ANSI for everything, if you need to maintain compatibility with existing code logic elsewhere in your project:
#include <windows.h>
ATOM RegMyWindowClass(HINSTANCE, LPCSTR);
HWND hListBox;
HINSTANCE hin;
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
if (IsWindowVisible(hwnd) && (!GetWindow(hwnd, GW_OWNER))) {
CHAR str[255];
if (GetWindowTextA(hwnd, str, 255)) {
SendMessage(hListBox, LB_ADDSTRING, 0, (LPARAM)str);
}
}
return TRUE;
}
LRESULT CALLBACK WndProc(
HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
// this is one case where it doesn't make sense to use ANSI
MessageBoxW(hWnd, L"Вы кликнули!", L"событие", 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
hListBox = CreateWindowA("LISTBOX", "", WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL,
0, 0, 400, 400, hWnd, (HMENU)1111, hin, NULL);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
LPCSTR lpzClass = "My Window Class!";
if (!RegMyWindowClass(hInstance, lpzClass))
return 1;
RECT screen_rect;
GetWindowRect(GetDesktopWindow(), &screen_rect);
int x = screen_rect.right / 2 - 200;
int y = screen_rect.bottom / 2 - 200;
HWND hWnd = CreateWindowA(lpzClass, "Window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE, x, y, 400, 400, NULL, NULL,
hInstance, NULL);
ShowWindow(hWnd, SW_SHOW);
EnumWindows(&EnumWindowsProc, 0);
if (!hWnd) return 2;
MSG msg = { 0 };
int iGetOk = 0;
while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (iGetOk == -1) return 3;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
ATOM RegMyWindowClass(HINSTANCE hInst, LPCSTR lpzClassName)
{
WNDCLASSA wcWindowClass = { 0 };
wcWindowClass.lpfnWndProc = &WndProc;
wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;
wcWindowClass.hInstance = hInst;
wcWindowClass.lpszClassName = lpzClassName;
wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;
return RegisterClassA(&wcWindowClass);
}
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 actually following a tutorial. I really want to get an answer because I will need to add icons to the window down the line. Getting images to show in the window would be the first step.
Sorry for some reason the update I added did not go through before. My solution is geared towards Unicode.
The corrected updated file is below :
#include <windows.h>
#include <commctrl.h>
using namespace std;
LPCWSTR szClassName = L"myWindowClass";
HWND hLogo;
HBITMAP hLogoImage;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void loadPictures();
void parentControls(HWND);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int icmdshow)
{
HWND hWnd;
WNDCLASSW wc = { 0 };
wc.style = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
if (!RegisterClassW(&wc))
{
const wchar_t Error01[] = L"Register Issue To Check On : "; /// Notice this
const wchar_t Error01_Caption[] = L"Error 01";
MessageBoxW(NULL, Error01, Error01_Caption, MB_OK | MB_ICONERROR);
return 0;
}
LPCWSTR parentWinTitle = L"My Window";
hWnd = CreateWindowW(szClassName, parentWinTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, NULL, NULL, NULL, NULL);
if (hWnd == NULL)
{
const wchar_t Error02[] = L"Window Creation Issue To Check On : ";
const wchar_t Error02_Caption[] = L"Window Creation Issue To Check On : ";
MessageBoxW(NULL, Error02, Error02_Caption, MB_OK | MB_ICONERROR);
}
ShowWindow(hWnd, icmdshow);
UpdateWindow(hWnd);
MSG msg = { 0 };
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
loadPictures(); /// Must be called first, Calling the Images function in Create
parentControls(hWnd);
break;
/* case WM_COMMAND:
switch (wParam)
{
}
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
void parentControls(HWND hWnd)
{
hLogo = CreateWindowW(WC_STATICW, NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP, 70, 25, 100, 100, hWnd, NULL, NULL, NULL);
SendMessageW(hLogo, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hLogoImage);
}
void loadPictures()
{ /// bmp image save in file with main.cpp
LPCWSTR myBmp = L"bitmap1.bmp";
hLogoImage = (HBITMAP)LoadImageW(NULL, myBmp, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
case WM_COMMAND:
switch(wp)
{
}
break;
parentControls(hWnd); <--- never gets here
loadPictures(); /// Calling the Images function in Create
break;
parentControls and loadPictures are never reached in this switch statement.
loadPictures should be called first.
Remove the two lines, put them in WM_CREATE as follows:
case WM_CREATE:
loadPictures(); /// Calling the Images function in Create
parentControls(hWnd);
break;
Someone told me the answer should be here instead of updated above. I am sure I will be made aware that it is wrong if I add it here. I figure that is why the updates didn't take when I tried them before in the original post above. Either way the update/Answer is below.
#include <windows.h>
#include <commctrl.h>
using namespace std;
LPCWSTR szClassName = L"myWindowClass";
HWND hLogo;
HBITMAP hLogoImage;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void loadPictures();
void parentControls(HWND);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int icmdshow)
{
HWND hWnd;
WNDCLASSW wc = { 0 };
wc.style = 0;
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.lpfnWndProc = WndProc;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
if (!RegisterClassW(&wc))
{
const wchar_t Error01[] = L"Register Issue To Check On : "; /// Notice this
const wchar_t Error01_Caption[] = L"Error 01";
MessageBoxW(NULL, Error01, Error01_Caption, MB_OK | MB_ICONERROR);
return 0;
}
LPCWSTR parentWinTitle = L"My Window";
hWnd = CreateWindowW(szClassName, parentWinTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 250, 200, NULL, NULL, NULL, NULL);
if (hWnd == NULL)
{
const wchar_t Error02[] = L"Window Creation Issue To Check On : ";
const wchar_t Error02_Caption[] = L"Window Creation Issue To Check On : ";
MessageBoxW(0, Error02, Error02_Caption, MB_OK | MB_ICONERROR);
}
ShowWindow(hWnd, icmdshow);
UpdateWindow(hWnd);
MSG msg = { 0 };
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
loadPictures(); /// Must be called first, Calling the Images function in Create
parentControls(hWnd);
break;
/* case WM_COMMAND:
switch (wParam)
{
}
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
void parentControls(HWND hWnd)
{
hLogo = CreateWindowW(WC_STATICW, NULL, WS_VISIBLE | WS_CHILD | SS_BITMAP, 70, 25, 100, 100, hWnd, NULL, NULL, NULL);
SendMessageW(hLogo, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hLogoImage);
}
void loadPictures()
{ /// bmp image save in file with main.cpp
LPCWSTR myBmp = L"bitmap1.bmp";
hLogoImage = (HBITMAP)LoadImageW(NULL, myBmp, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
I am trying to create an application with no visible windows, simply a tray icon. I have tried to cobble together various tutorials and answers here however haven't been able to get further than this. The context menu appears when I right click however is entirely blank. I'm also not sure how I would go about detection what I clicked on once I get it working.
The end goal is to be able to switch DNS servers by clicking one of two options in the context menu.
#include <Windows.h>
#include <shellapi.h>
#include <tchar.h>
#include <WinUser.h>
HINSTANCE gInstance = NULL;
LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wx;
HWND hWnd;
ZeroMemory(&wx, sizeof(WNDCLASSEX));
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = pWndProc;
wx.hInstance = hInstance;
wx.lpszClassName = (LPCWSTR)"DNSChanger";
RegisterClassEx(&wx);
CreateWindowEx(0, (LPCWSTR)"DNSChanger", (LPCWSTR)"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
gInstance = hInstance;
MSG stMsg;
while (GetMessage(&stMsg, NULL, 0, 0) > 0)
{
TranslateMessage(&stMsg);
DispatchMessage(&stMsg);
}
return 0;
}
LRESULT CALLBACK pWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
NOTIFYICONDATA niData;
ZeroMemory(&niData, sizeof(NOTIFYICONDATA));
switch (uMsg)
{
case WM_CREATE:
{
niData.cbSize = sizeof(NOTIFYICONDATA);
niData.uID = 1;
niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
niData.hIcon = LoadIcon(gInstance, MAKEINTRESOURCE(IDI_SHIELD));
niData.hWnd = hWnd;
niData.uCallbackMessage = WM_USER + 1;
Shell_NotifyIcon(NIM_ADD, &niData);
}
return 0;
case WM_DESTROY:
{
niData.hWnd = hWnd;
Shell_NotifyIcon(NIM_DELETE, &niData);
}
return 0;
case WM_USER + 1:
{
switch (LOWORD(lParam))
{
case WM_RBUTTONUP:
{
POINT lpClickPoint;
HMENU hPopMenu;
UINT uFlag = MF_BYPOSITION | MF_UNCHECKED | MF_STRING;
GetCursorPos(&lpClickPoint);
hPopMenu = CreatePopupMenu();
InsertMenu(hPopMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, WM_USER + 1, _T("Exit"));
SetForegroundWindow(hWnd);
TrackPopupMenu(hPopMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, lpClickPoint.x, lpClickPoint.y, 0, hWnd, NULL);
}
}
}
}
}
Don't use cast like this (LPCWSTR)"DNSChanger". This only hides the compiler error. The only reason your program works at all is because this error is repeated in 2 different places and it cancels out.
You meant to write L"DNSChanger".
Window procedure must return DefWindowProc(hWnd, uMsg, wParam, lParam);
In WM_DESTROY you must include PostQuitMessage(0); if you want to close the application.
Define a new constant to use in menu
const int IDM_EXIT = 100;
...
InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit");
The menu will send IDM_EXIT command as part WM_COMMAND message. Below are some recommended changes:
HINSTANCE gInstance = NULL;
const int IDM_EXIT = 100;
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static NOTIFYICONDATA niData = { sizeof(NOTIFYICONDATA) };
switch(uMsg)
{
case WM_CREATE:
{
niData.uID = 1;
niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
niData.hIcon = LoadIcon(gInstance, IDI_SHIELD);
niData.hWnd = hWnd;
niData.uCallbackMessage = WM_USER + 1;
Shell_NotifyIcon(NIM_ADD, &niData);
return 0;
}
case WM_DESTROY:
{
niData.hWnd = hWnd;
Shell_NotifyIcon(NIM_DELETE, &niData);
PostQuitMessage(0);
return 0;
}
case WM_COMMAND:
{
if(LOWORD(wParam) == IDM_EXIT)
PostQuitMessage(0);
break;
}
case WM_USER + 1:
{
WORD cmd = LOWORD(lParam);
if (cmd == WM_RBUTTONUP || cmd == WM_LBUTTONUP)
{
POINT pt;
GetCursorPos(&pt);
HMENU hmenu = CreatePopupMenu();
InsertMenu(hmenu, 0, MF_BYPOSITION | MF_STRING, IDM_EXIT, L"Exit");
TrackPopupMenu(hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, pt.x, pt.y, 0, hWnd, NULL);
}
break;
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
gInstance = hInstance;
WNDCLASSEX wx = { sizeof(WNDCLASSEX) };
wx.lpfnWndProc = WndProc;
wx.hInstance = hInstance;
wx.lpszClassName = L"DNSChanger";
RegisterClassEx(&wx);
CreateWindowEx(0, L"DNSChanger", L"", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
I have some experience with c++, and other languages but I've only made games before using c++ and I need to make a OBS plugin.. I was wondering if anyone could help..
I'm trying to create a window with -
int nHeight = 500;
int nWidth = 500;
#define metaData(lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\
CreateWindowExA(0L, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)
if (GetAsyncKeyState(VK_F5))
{
//MsgeBox::myMessage::createMessage(NULL, (LPCWSTR)L"Hello", (LPCWSTR)L"I See You.", MB_ICONWARNING | MB_CANCELTRYCONTINUE);
#define CreateWindow metaData;
}
It doesn't create a window, and it doesn't give an error.. when I call the messagebox it only appears once I try to close the window.. why is that?
How could I create a seperate window?
the tutorial im following is - https://msdn.microsoft.com/en-us/library/bb384843.aspx
You have to create a message procedure then respond to key messages. For example
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_KEYDOWN:
if (wp == VK_F5)
CreateWindow(L"ChildClass", L"Child window",
WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION,
0, 0, 300, 200, hwnd, 0, 0, 0);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
Note that you have to register a second class name for "ChildClass" and then create a different message procedure for this child class.
Then you add a separate function called ChildProc which is similar to WndProc. For example:
#define UNICODE
#include <Windows.h>
HINSTANCE g_hinstance = 0;
LRESULT CALLBACK ChildProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_KEYDOWN:
{
if (wp == VK_F5)
{
MessageBox(0, L"VK_F5 detected", 0, 0);
if (!CreateWindow(L"ChildClass", L"ChildTitle",
WS_VISIBLE | WS_POPUPWINDOW | WS_CAPTION, 100, 100, 300, 200,
hwnd, 0, g_hinstance, 0))
{
DWORD err = GetLastError();
wchar_t buf[100];
wsprintf(buf, L"%d\n", err);
MessageBox(0, buf, 0, 0);
}
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
{
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wcex.lpszClassName = L"MainClass";
RegisterClassEx(&wcex);
wcex.lpszClassName = L"ChildClass";
wcex.lpfnWndProc = ChildProc;
RegisterClassEx(&wcex);
CreateWindow(L"MainClass", L"MainTitle", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0, 0, 600, 400, 0, 0, hInstance, 0);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
I'm trying to do sort in a ListView. Didn't found any complete example how to do it, only a pieces of code.
I've already created ListView, added columns and items, specified my Comp function. However my problem is that lp1 and lp2 are always 0. I've checked documentation and it says : "These are the values that were specified in the lParam member of the items' LVITEM structure when they were inserted into the list." which I do set.
Here is the code :
#include <windows.h>
#include <stdio.h>
#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")
HWND ListView;
HWND hwnd;
LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow)
{
MSG messages;
WNDCLASSEX wincl = { 0 };
wincl.lpszClassName = "Testtttt";
wincl.lpfnWndProc = WindowProc;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof(WNDCLASSEX);
wincl.hIcon = 0;
wincl.hIconSm = 0;
wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
wincl.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0,0,0));// COLOR_BACKGROUND;
wincl.hInstance = GetModuleHandle(NULL);
RegisterClassEx(&wincl);
hwnd = CreateWindowEx(
0,
wincl.lpszClassName,
"Test",
WS_SYSMENU | WS_EX_STATICEDGE | WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
1000,
500,
hwnd,
NULL,
GetModuleHandle(NULL),
NULL);
RECT rec;
GetClientRect(hwnd, &rec);
SetWindowPos(ListView, 0, 0, 0, rec.right, rec.bottom - 23, 0);
ShowWindow(hwnd, nCmdShow);
while (GetMessage(&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
}
void AddListViewItem(char item, char *text)
{
static int i;
LVITEM lis;
lis.mask = LVIF_TEXT /*| LVIF_PARAM*/;
lis.pszText = (LPSTR)(text);
lis.iItem = i;
lis.iSubItem = item;
lis.lParam = i;
if (item==1)
i++;
if (item == 0)
ListView_InsertItem(ListView, &lis);
else
SendMessage(ListView, LVM_SETITEM, 0, (LPARAM)&lis);
}
int CALLBACK myCompFunc(LPARAM lp1, LPARAM lp2, LPARAM sortParam)
{
bool isAsc = (sortParam > 0);
int column = abs(sortParam) - 1;
char tmp[128];
sprintf_s(tmp,sizeof tmp, "%d %d %d", lp1, lp2, column);
MessageBox(0, (LPCSTR)tmp, "myCompFunc", MB_OK);
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_NOTIFY)
{
LPNMHDR lpnmh = (LPNMHDR)lParam;
if (lpnmh->idFrom == 8553)
if (lpnmh->code == LVN_COLUMNCLICK)
{
NMLISTVIEW* pListView = (NMLISTVIEW*)lParam;
ListView_SortItems(ListView, myCompFunc, pListView->iSubItem);
}
}
else if (message == WM_CREATE)
{
ListView = CreateWindow(WC_LISTVIEW, (LPCSTR)L"", (WS_CHILD | WS_VISIBLE | LVS_REPORT), 0, 0, 900, 500, hwnd, (HMENU)8553, GetModuleHandle(NULL), NULL);
SendMessage(ListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); // Set style
LVCOLUMN listColumn = { 0 };
listColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
listColumn.pszText = "Column1";
listColumn.cx = 150;
listColumn.fmt = LVCFMT_LEFT;
ListView_InsertColumn(ListView, 0, &listColumn);
listColumn.pszText = "Column2";
listColumn.cx = 150;
listColumn.iSubItem = 1;
ListView_InsertColumn(ListView, 1, &listColumn);
{
AddListViewItem(0, "a");
AddListViewItem(1, "a 1");
AddListViewItem(0, "b");
AddListViewItem(1, "b 1");
AddListViewItem(0, "c");
AddListViewItem(1, "c 1");
}
}
else if (message == WM_DESTROY)
{
PostQuitMessage(0);
}
else
return DefWindowProc(hwnd, message, wParam, lParam);
return DefWindowProc(hwnd, message, wParam, lParam);
return 0;
}