我寫了一個簡單的程序;它由一個主窗口和它上面的TextBox窗口組成。 TextBox是50%透明的。當TextBox獲取消息時,它會在主窗口上繪製一條藍線。Win32 API:透明不起作用
問題是「透明」實際上根本不透明。如果藍線與文本框中的文本交叉,則文本剛剛被刪除,儘管文本位於上方。反之亦然:如果我開始打字,文本行中的一部分行將消失,而不是閃耀。 這是一個錯誤?或者我錯過了什麼?
#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);
}
}
不知道是很重要的,但我還要提到,我只Ubuntu下的測試與葡萄酒,因爲我的Windows由this bug搞砸了。無論如何,我希望這個問題不在Wine本身。 對於大量的代碼抱歉,我真的不知道要刪除什麼以使其更小。
'WS_EX_LAYERED',從而'SetLayeredWindowAttributes()'和'UpdateLayeredWindow()'不能與孩子使用的控件之前的Windows 8 –
你可以嘗試添加父窗口上的'WS_CLIPCHILDREN'樣式。另請注意,Windows 8之前不支持分層的子窗口。 –
@RemyLebeau,@JonathanPotter [如MSDN所述](http://msdn.microsoft.com/zh-cn/library/ms997507.aspx),WS_EX_LAYERED '是從Windows 2000開始引入的,自此以後就支持分層的窗口。 –