C++ Win32 API:transparency不';行不通
我写了一个简单的程序;它由一个主窗口和上面的文本框窗口组成。文本框是50%透明的。当TextBox收到消息时,它会在主窗口上画一条蓝线 问题是“透明”实际上根本就不透明。如果蓝线与文本框中的文本交叉,则文本将被删除,尽管文本位于上方。反之亦然:如果我开始打字,文本行中的一部分就会消失,而不是闪烁。 这是虫子吗?还是我遗漏了什么C++ Win32 API:transparency不';行不通,c++,winapi,transparency,C++,Winapi,Transparency,我写了一个简单的程序;它由一个主窗口和上面的文本框窗口组成。文本框是50%透明的。当TextBox收到消息时,它会在主窗口上画一条蓝线 问题是“透明”实际上根本就不透明。如果蓝线与文本框中的文本交叉,则文本将被删除,尽管文本位于上方。反之亦然:如果我开始打字,文本行中的一部分就会消失,而不是闪烁。 这是虫子吗?还是我遗漏了什么 #include <windows.h> #include <stdio.h> #define IDC_MAIN_EDIT 101 void
#include <windows.h>
#include <stdio.h>
#define IDC_MAIN_EDIT 101
void DrawInWindow(HWND hWndToPaint){
HDC hdc = GetDC(hWndToPaint);
if(!hdc)printf("Invalid handle\n");
HPEN hPen = CreatePen(PS_SOLID,5,RGB(0, 0, 255));
SelectObject(hdc, hPen);
static float x=620, y=1, tg=0.5, ctg=2;
static int Xone = 1, Yone = 1;//depending on later recalculation this may become negative
MoveToEx(hdc,(int)x,(int)y,NULL);
if(tg<1){
y+=tg;
x+=Xone;
}else{
y+=Yone;
x+=ctg;
}
if(!LineTo(hdc, (int)x, (int)y) )printf("There are paint problem\n");
ReleaseDC(hWndToPaint,hdc);
//Now recalculate direction
RECT WndRect;
GetClientRect(hWndToPaint,&WndRect);
if(x>=WndRect.right){
if(ctg>0)ctg*=-1;//make negative
Xone=-1;
}
if(x<=WndRect.left){
if(ctg<0)ctg*=-1;//make positive
Xone=1;
}
if(y>=WndRect.bottom){
if(tg>0)tg*=-1;//make negative
Yone=-1;
}
if(y<=WndRect.top){
if(tg<0)tg*=-1;//make positive
Yone=1;
}
}
int CALLBACK EnumWindowsFunc(HWND hWnd, LPARAM lParam){
DrawInWindow(hWnd);
return false;
}
void PaintInMainWnd(){
EnumWindows(EnumWindowsFunc,0L);//Getting the handle of main window to draw
}
LRESULT __stdcall MyMainCallBckProcedure( HWND window, unsigned msg, WPARAM wp, LPARAM lp ){
switch(msg){
case WM_KEYDOWN:
if(wp == VK_ESCAPE)PostQuitMessage(0);
break;
case WM_DESTROY:
printf("\ndestroying window\n");
PostQuitMessage(0);
return 0;
case WM_SIZE:{
HWND hEdit;
RECT rcClient;
GetClientRect(window, &rcClient);
hEdit = GetDlgItem(window, IDC_MAIN_EDIT);
SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
break;
}
default:
return DefWindowProc( window, msg, wp, lp ) ;
}
}
WNDPROC lpEditWndProc;
LRESULT CALLBACK MyEditCallBckProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
if( (uMsg == WM_CHAR) && (wParam == VK_ESCAPE) )
{
PostQuitMessage(0);
return 0;
}
PaintInMainWnd();
lpEditWndProc(hWnd, uMsg, wParam, lParam);
}
bool CreateWindows(){
const char* const myclass = "myclass";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, MyMainCallBckProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW+1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };
if(RegisterClassEx(&wndclass)<0){
printf("ERR: in registering window class\n");
return false;
}
//Creating window
HWND window = CreateWindowEx( 0, myclass, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
640, 480, 0, 0, GetModuleHandle(0), 0 );
if(!window){
printf("ERR: in creating window\n");
return false;
}
ShowWindow( window, SW_SHOWDEFAULT );
//creating TextBox on the window
HFONT hfDefault;
HWND hEdit;
hEdit = CreateWindowEx(0, "edit", "",
WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
window, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
if(hEdit == NULL){
MessageBox(window, "Could not create edit box.", "Error", MB_OK | MB_ICONERROR);
return false;
}
hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
//Now resize TextBox to fill whole parent window
RECT RectSize;
GetClientRect(window,&RectSize);
hEdit = GetDlgItem(window,IDC_MAIN_EDIT);
SetWindowPos(hEdit, 0,0,0,RectSize.right,RectSize.bottom,SWP_NOZORDER);
//Let's try to catch some messages in TextBox...
lpEditWndProc = (WNDPROC)SetWindowLongPtr(hEdit, GWL_WNDPROC, (LONG_PTR)&MyEditCallBckProcedure);
//Making hEdit transparent
SetWindowLongPtr(hEdit,GWL_EXSTYLE, WS_EX_LAYERED | GetWindowLongPtr(hEdit, GWL_EXSTYLE) );
SetLayeredWindowAttributes(hEdit, 0, (255*50)/100, LWA_ALPHA);
return true;
//###
}
int main(){
if(!CreateWindows() ){printf("Something gone wrong\n");return 1;}
MSG msg;
while(GetMessage(&msg,0,0,0) ){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
#包括
#包括
#定义IDC_MAIN_EDIT 101
空窗(HWND hWndToPaint){
HDC HDC=GetDC(hWndToPaint);
如果(!hdc)printf(“无效句柄\n”);
HPEN HPEN=CreatePen(PS_SOLID,5,RGB(0,0255));
选择对象(hdc、hPen);
静态浮动x=620,y=1,tg=0.5,ctg=2;
静态int-Xone=1,Yone=1;//根据以后的重新计算,该值可能变为负值
MoveToEx(hdc,(int)x,(int)y,NULL);
如果(tg=WndRect.right){
如果(ctg>0)ctg*=-1;//使其为负值
Xone=-1;
}
如果(x0)tg*=-1;//使负
Yone=-1;
}
如果(y我找到了解决方法。我创建了背景顶层窗口,并使前景窗口具有50%的透明度。我在背景窗口中绘制线条。如果前窗口移动或调整大小,后窗口会在WM_WINDOWPOSCHANGED
消息的帮助下做出相应的反应,它会在每一次移动/调整大小时发送
无论如何,此解决方案有点脏,因为:
Linux/wine特定的问题:1)显示管理器不装饰wine的透明窗口(但这可以通过使第二个窗口0%透明来避免)2)拖动窗口抖动,但第二个窗口笔直移动。所有操作系统特定的问题:任务栏中显示第二个窗口。理论上,可以通过向无主窗口添加WS_EX_TOOLWINDOW
来避免最后一个
要防止窗口按钮被放置在任务栏上,请创建
具有WS_EX_TOOLWINDOW扩展样式的无主窗口
但是,至少在葡萄酒中,它不起作用。嗯,我希望这是一个错误:)
#包括
#包括
#定义IDC_MAIN_EDIT 101
HWND-hBackWnd;
空窗(HWND hWndToPaint){
HDC HDC=GetDC(hWndToPaint);
如果(!hdc)printf(“无效句柄\n”);
HPEN HPEN=CreatePen(PS_SOLID,5,RGB(0,0255));
选择对象(hdc、hPen);
静态浮动x=620,y=1,tg=0.5,ctg=2;
静态int-Xone=1,Yone=1;//根据以后的重新计算,该值可能变为负值
MoveToEx(hdc,(int)x,(int)y,NULL);
如果(tg=WndRect.right){
如果(ctg>0)ctg*=-1;//使其为负值
Xone=-1;
}
如果(x0)tg*=-1;//使负
Yone=-1;
}
如果(ycy)IsRepaint=true;
else IsRepaint=false;
移动窗口(hBackWnd,pNewPos->x,pNewPos->y,pNewPos->cx,pNewPos->cy,IsRepaint);
打破
}
违约:
返回DefWindowProc(窗口、消息、wp、lp);
}
}
WNDPROC lpEditWndProc;
LRESULT回调MyEditCallBckProcedure(HWND HWND、UINT uMsg、WPARAM WPARAM、LPARAM LPARAM){
if((uMsg==WM_CHAR)&&(wParam==VK_ESCAPE))
{
PostQuitMessage(0);
返回0;
}
绘图窗口(hBackWnd);
lpEditWndProc(hWnd、uMsg、wParam、lParam);
}
bool CreateWindows(){
//创建后窗口
const char*backwnd=“backwnd”;
WNDCLASSEX backwndclass={sizeof(WNDCLASSEX),CS_DBLCLKS,MyMainCallBckProcedure,
0,0,GetModuleHandle(0),LoadIcon(0,IDI_应用程序),
加载光标(0,IDC箭头),HBRUSH(彩色窗口+1),
0,backwnd,LoadIcon(0,IDI_应用程序)};
如果(RegisterClass(&backwndclass)WS\u EX\u LAYERED
,因此SetLayeredWindowAttributes()
和UpdateLayeredWindow()
不能与Windows 8之前的子控件一起使用。您可以尝试在父窗口上添加WS\u CLIPCHILDREN
样式。还要注意,在Windows 8之前不支持分层子窗口。@RemyLebeau、@JonathanPotter、WS\u EX\u layered
自Windows 2000年引入,分层窗口在Windows中得到支持这次是ce。@YagamyLight:是的,是的。但如果你更仔细一点,它还说:“Windows 8:顶级窗口和子窗口支持WS_EX_LAYERED
样式。以前的Windows版本只支持顶级窗口的WS_EX_LAYERED
。”@雷米尔博好吧,那么从目前的情况来看,我的问题似乎没有意义……非常感谢。
#include <windows.h>
#include <stdio.h>
#define IDC_MAIN_EDIT 101
HWND hBackWnd;
void DrawInWindow(HWND hWndToPaint){
HDC hdc = GetDC(hWndToPaint);
if(!hdc)printf("Invalid handle\n");
HPEN hPen = CreatePen(PS_SOLID,5,RGB(0, 0, 255));
SelectObject(hdc, hPen);
static float x=620, y=1, tg=0.5, ctg=2;
static int Xone = 1, Yone = 1;//depending on later recalculation this may become negative
MoveToEx(hdc,(int)x,(int)y,NULL);
if(tg<1){
y+=tg;
x+=Xone;
}else{
y+=Yone;
x+=ctg;
}
if(!LineTo(hdc, (int)x, (int)y) )printf("There are paint problem\n");
ReleaseDC(hWndToPaint,hdc);
//Now recalculate direction
RECT WndRect;
GetClientRect(hWndToPaint,&WndRect);
if(x>=WndRect.right){
if(ctg>0)ctg*=-1;//make negative
Xone=-1;
}
if(x<=WndRect.left){
if(ctg<0)ctg*=-1;//make positive
Xone=1;
}
if(y>=WndRect.bottom){
if(tg>0)tg*=-1;//make negative
Yone=-1;
}
if(y<=WndRect.top){
if(tg<0)tg*=-1;//make positive
Yone=1;
}
}
LRESULT __stdcall MyMainCallBckProcedure( HWND window, unsigned msg, WPARAM wp, LPARAM lp ){
switch(msg){
case WM_KEYDOWN:
if(wp == VK_ESCAPE)PostQuitMessage(0);
break;
case WM_DESTROY:
printf("\ndestroying window\n");
PostQuitMessage(0);
return 0;
case WM_SIZE:
HWND hEdit;
RECT rcClient;
GetClientRect(window, &rcClient);
hEdit = GetDlgItem(window, IDC_MAIN_EDIT);
SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);
break;
case WM_WINDOWPOSCHANGED:{//LPARAM is a ptr to WINDOWPOS
RECT BckWndRect;
if(!GetWindowRect(hBackWnd, &BckWndRect) )printf("ERR: getting backwnd rectangle\n");
bool IsRepaint;
WINDOWPOS* pNewPos = (WINDOWPOS*)lp;
if(BckWndRect.left+BckWndRect.right != pNewPos->cx
|| BckWndRect.top+BckWndRect.bottom != pNewPos->cy)IsRepaint = true;
else IsRepaint = false;
MoveWindow(hBackWnd, pNewPos->x, pNewPos->y, pNewPos->cx, pNewPos->cy, IsRepaint);
break;
}
default:
return DefWindowProc( window, msg, wp, lp ) ;
}
}
WNDPROC lpEditWndProc;
LRESULT CALLBACK MyEditCallBckProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
if( (uMsg == WM_CHAR) && (wParam == VK_ESCAPE) )
{
PostQuitMessage(0);
return 0;
}
DrawInWindow(hBackWnd);
lpEditWndProc(hWnd, uMsg, wParam, lParam);
}
bool CreateWindows(){
//creating back window
const char* backwnd = "backwnd";
WNDCLASSEX backwndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, MyMainCallBckProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW+1),
0, backwnd, LoadIcon(0,IDI_APPLICATION) };
if(RegisterClassEx(&backwndclass)<0){
printf("ERR: in registering second window class\n");
return false;
}
hBackWnd = CreateWindowEx( 0, backwnd, "title", WS_EX_TOOLWINDOW |
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
640, 480, 0, 0, GetModuleHandle(0), 0 );
if(!hBackWnd){
printf("ERR: in creating background window\n");
return false;
}
ShowWindow( hBackWnd, SW_SHOWDEFAULT );
//Creating front window
const char* const frontwnd = "frontwnd";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, MyMainCallBckProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW+1),
0, frontwnd, LoadIcon(0,IDI_APPLICATION) };
if(RegisterClassEx(&wndclass)<0){
printf("ERR: in registering foreground window class\n");
return false;
}
HWND window = CreateWindowEx( 0, frontwnd, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
640, 480, 0, 0, GetModuleHandle(0), 0 );
if(!window){
printf("ERR: in creating foreground window\n");
return false;
}
ShowWindow( window, SW_SHOWDEFAULT );
//creating textbox
HWND hEdit = CreateWindowEx( 0, "edit", "", WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL
| ES_MULTILINE | ES_AUTOVSCROLL, CW_USEDEFAULT, CW_USEDEFAULT, 640,
480, window, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(0), 0 );
HFONT hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));
//Let's try to catch some messages in TextBox...
lpEditWndProc = (WNDPROC)SetWindowLongPtr(hEdit, GWL_WNDPROC, (LONG_PTR)&MyEditCallBckProcedure);
//Making foreground window transparent
SetWindowLongPtr(window,GWL_EXSTYLE, WS_EX_LAYERED | GetWindowLongPtr(window, GWL_EXSTYLE) );
SetLayeredWindowAttributes(window, 0, (255*50)/100, LWA_ALPHA);
return true;
//###
}
int main(){
if(!CreateWindows() ){printf("Something gone wrong\n");return 1;}
MSG msg;
while(GetMessage(&msg,0,0,0) ){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}