I am building an app with WinAPI that consists of basically two main parts: a panel on the left hand that is always shown and an area on the right that changes based on which screen is shown. Currently the left-hand, static area is just being drawn onto the main window; however, for I don't believe that I can simply draw the right area onto the main window as it needs to change. Therefore, I believe that I need to create windows there and just control what is shown by controlling its visibility. I read a lot about the Multiple Document Interface in the MSDN, but I'm not sure if that is what I am looking for. Specifically, I don't want the child windows to act like real windows, meaning I don't want them to have a title or icon or be able to be minimized, closed, resized, or moved. Basically, I want them to just be frames that hold controls/D2D geometry. What would be the best way to go about implementing this?
As Remy said, you only need to re-register a new window and then create it as a subclass in the main window. You don't need to set the title and maximize and minimize buttons in setting the style, and you can also decide by yourself whether you need to deal with the WNDPROC function of the subclass.
Here is a sample(In order to display the child window, I set its background to black.):
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK cldWndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR szCmdLine, _In_ int iCmdShow)
{
static TCHAR szAppName[] = TEXT("hello windows");
static TCHAR cldwndName[] = TEXT("test app");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
}
hwnd = CreateWindow(szAppName,
TEXT("the hello program"),
WS_OVERLAPPEDWINDOW,
100,
100,
800,
600,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
WNDCLASS cldclass;
cldclass.style = CS_HREDRAW | CS_VREDRAW;
cldclass.lpfnWndProc = cldWndProc;
cldclass.cbClsExtra = 0;
cldclass.cbWndExtra = 0;
cldclass.hInstance = hInstance;
cldclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
cldclass.hCursor = LoadCursor(NULL, IDC_ARROW);
cldclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
cldclass.lpszMenuName = NULL;
cldclass.lpszClassName = cldwndName;
if (!RegisterClass(&cldclass))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
}
HWND hwnd1 = CreateWindow(cldwndName,
NULL,
WS_CHILD|WS_VISIBLE,
400,
200,
200,
300,
hwnd,
NULL,
hInstance,
NULL);
ShowWindow(hwnd1, iCmdShow);
UpdateWindow(hwnd1);
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
LRESULT CALLBACK cldWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
It works for me:
Related
My requirement is that:
I want to detect left mouse click event and take some action. Mouse click should get detected only on the given application if mouse click is on other application then it should not take action.
Currently I am using :
mousehook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, NULL, 0);
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT k = (PKBDLLHOOKSTRUCT)(lParam);
POINT p;
if (wParam == WM_LBUTTONDOWN)
{
// MB1 click
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
but it is working for mouse click anywhere on the desktop screen. I want to detect it for current application only.
If you have Win32 application. Probably you can handle mouse events in your Window proc itself.
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
// your code
return 0;
case WM_LBUTTONUP:
// your code
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Window creation:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("Connect");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
if (!RegisterClass(&wndclass)) {
MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Connect−the−Points Mouse Demo"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
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.
I set Character set to Use Unicode Character Set but when show window, its title still have square character. How can I fix it? Thank!
#include <windows.h>
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX wClass;
ZeroMemory(&wClass, sizeof(WNDCLASSEX));
wClass.cbClsExtra = NULL;
wClass.cbSize = sizeof(WNDCLASSEX);
wClass.cbWndExtra = NULL;
wClass.hbrBackground = (HBRUSH)COLOR_WINDOW;
wClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wClass.hIcon = NULL;
wClass.hIconSm = NULL;
wClass.hInstance = hInst;
wClass.lpfnWndProc = (WNDPROC)WinProc;
wClass.lpszClassName = L"Window Class";
wClass.lpszMenuName = NULL;
wClass.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wClass);
HWND hWnd = CreateWindowEx(
NULL,
L"Window Class",
L"/ce 但是,这样做并不能保证在对话框编辑器创建控件之前将加载所需的库。",
WS_OVERLAPPEDWINDOW,
200, 200, 300, 0, NULL, NULL, hInst, NULL);
ShowWindow(hWnd, nShowCmd);
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
I'm posting this as an answer, just because I can't put images in a comment ...
I just did exactly what you did, same code, Windows 8.1 x64 VS2012 UK English, and here's the result I get:
Unless you ignored the prompt to save your source file as a UNICODE file, you should have got the same result - I don't see that there are any other differences unless you have some strange settings in your Region/Language section of Control Panel.
If you still get the problem, you'll have to double-check all of your settings and maybe post more code and/or a dump of your compiler command line.
I have written a small program to create a window. I have made this program before, but now I'm trying to recollect all the things for myself.
When I was done writing the program, the window won't appear, and when I compare my code to the book I'm learning from, its the same. What am I missing/doing wrong?
#include <windows.h>
#include <WindowsX.h>
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
{
HWND hWnd;
// information for the window class
WNDCLASSEX wc;
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.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "WindowClass1";
RegisterClassEx(&wc);
// Create Window
hWnd = CreateWindowEx( NULL,
"WindowClass",
"My Program",
WS_OVERLAPPEDWINDOW,
100,
100,
600,
480,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hWnd, SW_SHOWDEFAULT);
MSG msg;
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_DESTROY:
{
PostQuitMessage(0);
return 0;
} break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
Compare class names:
wc.lpszClassName = "WindowClass1";
hWnd = CreateWindowEx( NULL, "WindowClass", ...
The best way to find such errors is to check return code of every API.
Weird issue:
Open a large notepad window
create a toolwindow (style WS_EX_TOOLWINDOW)
create 2 more windows (normal overlapped) (WS_OVERLAPPED)
close those 2 overlapped windows (child of desktop or the toolwindow)
the toolwindow jumps behind the notepad window
Does anyone know why this is the case? Or what I could be doing wrong? I would say 'bug in windows', but that is rarely the case.
To answer questions:
It is not a dialog window, but a full window. If i make it have correct children (ie: not a child of desktop), the taskbar entry for the children do not appear (probably easily fixable), but either way, the bug still happens.
I have included example code that shows the issue. I am hoping I am just creating the window wrong or required to respond to a message I am not responding to.
In this example, a tool window will open (no task bar entry, which is what is wanted). Then you click on that window, a subwindow will open. You click on the subwindow, another window will open. Then close both new subwindows and the original window, instead of getting focus, jumps immediately to behind other windows (notepad, etc).
Thanks for any help!
Example code to clarify:
// WindowToback.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "WindowToback.h"
// Global Variables:
HINSTANCE g_instance;
HWND g_mainWnd = NULL;
wchar_t *szWindowClass = L"WindowToBackSub";
wchar_t *szWindowClass2 = L"WindowToBackSub2";
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProc2(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);
MSG msg;
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}
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_WINDOWTOBACK));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINDOWTOBACK);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassEx(&wcex);
wcex.lpfnWndProc = WndProc2;
wcex.lpszClassName = szWindowClass2;
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
g_instance = hInstance;
g_mainWnd = CreateWindowEx(WS_EX_TOOLWINDOW,szWindowClass, szWindowClass,WS_OVERLAPPED,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!g_mainWnd) return FALSE;
ShowWindow(g_mainWnd, nCmdShow);
UpdateWindow(g_mainWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
{
HWND l_hwnd = CreateWindow(szWindowClass2, szWindowClass2, WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_instance, NULL);
ShowWindow(l_hwnd,SW_SHOW);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
{
HWND l_hwnd = CreateWindow(szWindowClass2, szWindowClass2, WS_VISIBLE | WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, g_instance, NULL);
ShowWindow(l_hwnd,SW_SHOW);
}
break;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
This isn't surprising. In fact, it's exactly the behavior I'd expect.
You're tool window isn't jumping down; rather Notepad is jumping up.
You closed the window that had activation. The system is going to activate the next-highest top-level window in the z-order. Your tool window doesn't a count as a top-level window in this regard (that's part of what being a tool window means). So Notepad gets activated, and it comes to the top.
If you want your tool window to get activated instead, you probably don't really want a tool window.
Are the three windows dialogs to another main window or are they applications in their own right?
If they are dialog windows then I would check that their parent window is correctly assigned.
If they are application windows then I would check that they are appearing in the taskbar.
Without more information about the problem it is hard to give a more meaningful answer.