最近寫了個截屏的程式,但是沒有螢屏顯示,就想著在螢屏上標記個框框啥的。有鑒于此,寫了下面的的代碼。
然而but出問題了。。。。
def checkarea(argTitle,argTL,argBR,argPostion="T"):
'''
在螢屏上標注引數區域,文字+矩形框
argPostion:T,L,B,R,I對應top,left,bottom,right,in,大小寫不敏感,其他取值默認為T
'''
hwnd=None
hwndDC=win32gui.GetWindowDC(hwnd)
# 文字部分
tw,th=win32gui.GetTextExtentPoint32(hwndDC,argTitle) # 獲取文字長寬
tps=argPostion.upper()
txtps=(0,0)
# # 計算文字頂點坐標
if tps == "L":
txtps=(argTL[0]-tw-2,argTL[1])
elif tps == "B":
txtps=(argTL[0],argBR[1]+2)
elif tps == "R":
txtps=(argBR[0]+2,argTL[1])
elif tps == "I":
txtps=tuple(x+2 for x in argTL)
else:
txtps=(argTL[0],argTL[1]-th-2)
# # 文字背景透明
win32gui.SetBkMode(hwndDC, win32con.TRANSPARENT)
preClr= win32gui.SetTextColor(hwndDC,win32api.RGB(255,0,255))
win32gui.ExtTextOut(hwndDC,*txtps,0,None,argTitle)
win32gui.SetTextColor(hwndDC,preClr)
# 矩形框部分
hPen= win32gui.CreatePen(win32con.PS_SOLID,1,win32api.RGB(255,0,255))
win32gui.SelectObject(hwndDC,hPen)
hBrush = win32gui.GetStockObject(win32con.NULL_BRUSH)
preBrush = win32gui.SelectObject(hwndDC,hBrush)
win32gui.Rectangle(hwndDC,* argTL , * argBR)
win32gui.SelectObject(hwndDC,preBrush)
# 資源回收
win32gui.DeleteObject(hPen)
win32gui.DeleteObject(hBrush)
win32gui.DeleteObject(preBrush)
win32gui.ReleaseDC(hwnd,hwndDC)
return True
現象1:由于pywin32沒有textout函式,只能使用ExtTextOut輸出,使用ExtTextOut輸出文字后,總有個色塊,無法透明。
無論SetBkMode為何模式,透明模式,顯示背景黑色。非透明模式,顯示背景灰色。
現象2:理論上,該函式已經releaseDC了,但是第二次再寫,就會出現文字重疊問題。雖然在螢屏上畫了框,寫了文字,稍微有個視窗一動就被重繪掉,沒了,但是繼續運行本函式,文字就會重疊在上次寫的文字之上。只有Win+L鎖定以后,才能消除。
問題:
1 如何讓我在螢屏上ExtTextOut的文字背景透明?
2 如何重繪掉上一次ExtTextOut的文字?
uj5u.com熱心網友回復:
上次寫的 內容 必須 清除。那個 矩形區必須 Invalidate ,讓 桌面 重繪!
uj5u.com熱心網友回復:
填充背景 重新繪制字體不能擦除的色塊是指游標么? 試試 HideCaret SetCaretPos 再 ShowCaret
uj5u.com熱心網友回復:
理論上我知道,實際上搞不清楚重繪的程序,能不能給點代碼?
我在函式最前面加了
# 重繪視窗
hwnd=win32gui.GetDesktopWindow()
win32gui.RedrawWindow(hwnd,(1000,300,1400,700),0,win32con.RDW_UPDATENOW)
print("RedrawWindow getlasterror",win32api.GetLastError())
hwndDC=win32gui.GetWindowDC(hwnd)
沒有效果啊!!!!
uj5u.com熱心網友回復:
ExtTextOut繪制在螢屏上的字體總是帶有背景顏色啊!
uj5u.com熱心網友回復:


矩形倒是空心的。但是文字總有背景色。其實說背景色并不準確,如果SetBkMode設定的不是透明,設定O開頭的那個引數,則背景色是灰色,設定透明則是黑色。
ps:
我在這個函式后面加了個獲取DC并截圖的代碼,整個程式執行2遍,第三遍文字背景就透明了,只是文字照樣重疊。。。瘋了我。。。。
uj5u.com熱心網友回復:
MSDN 檔案上有說明The ExtTextOut function draws a character string by using the currently selected font, background color, and text color.
因此你得先設定字體和背景色
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
int nSaveDC = SaveDC(hdc);
RECT rt;
GetClientRect(hWnd, &rt);
//DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
COLORREF txColor = SetTextColor(hdc, RGB(255, 0, 0));
COLORREF bkColor = SetBkColor(hdc, RGB(255, 255, 255));
ExtTextOut(hdc, 10, 10, 0, NULL, szHello, _tcslen(szHello), NULL);
SetBkColor(hdc, bkColor);
SetTextColor(hdc, txColor);
RestoreDC(hdc, nSaveDC);
EndPaint(hWnd, &ps);
break;
}
uj5u.com熱心網友回復:
第一,我使用GetDesktopWindow獲取的是GetWindowDC才能畫圖,BeginPaint - EndPaint 是不能畫圖的,我查看了BeginPaint的&ps回傳值,DesktopWindow是沒有客戶區的。
第二,我設定了bkmode,沒有動bkcolor,自然有個默認背景色。事實上我設定的bkmode為透明
我理解你的代碼含義為:
用hwnd獲取應用的客戶去DC,然后保存這個DC,然后textout文字,最后用前面的DC覆寫。
那豈不是畫了直接被覆寫掉?等于沒畫?
uj5u.com熱心網友回復:
void CDesktopRectRefreshDlg::ReFreshDesktopRect(RECT *prc,HRGN rgn,BOOL bDraw)
{
HWND hWndDesk = ::GetDesktopWindow();
HDC hDC=::GetWindowDC(hWndDesk);
if(bDraw)
{// red pen
HPEN pen=CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
HPEN hOldPen=(HPEN)::SelectObject(hDC,pen);
// Pattern Brush
HBRUSH hOldBrush = (HBRUSH)::SelectObject(hDC,m_BackBr);
// draw circle
::Ellipse(hDC,prc->left,prc->top,prc->right,prc->bottom);
// resume
::SelectObject(hDC,hOldPen);
::SelectObject(hDC, hOldBrush);
}
else
{
::RedrawWindow(hWndDesk,0, rgn, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);// 1 4 80 =0x85);
}
}
uj5u.com熱心網友回復:
https://download.csdn.net/download/schlafenhamster/4362660桌面小球.zip
包含3個工程。
1。DeskBallBmp 一個圓位圖在桌面上移動,但圓內有閃爍。
2。DeskBallCli 一個圓位圖在帶背景的客戶區內移動,圓內無閃爍。
3。DeskBallWin 一個圓型視窗在桌面上移動,圓內無閃爍。
uj5u.com熱心網友回復:
對比了我們的代碼區別,主要在于RedrawWindow
RedrawWindow(hwnd,(1000,300,1400,700),0,win32con.RDW_UPDATENOW)
hWndDesk = hwnd
Rect 你用的是0 應該代表全屏,我用的是一個區域
RGN是什么?可否設定為0?哪個api獲取?查了一下,貌似Rect和RGN都為0 更新客戶區域,而Desktop無客戶區域。那么問題:RGN如何獲取?
Redraw引數,我用的是RDW_UPDATENOW。
我按照你寫的ReDrawWindows改寫了
win32gui.RedrawWindow(hwnd,None,None,win32con.RDW_INVALIDATE|win32con.RDW_ERASE|win32con.RDW_ALLCHILDREN)
在GetDesktopWindow后面加上這個重繪操作,仍舊是文字,框重疊
uj5u.com熱心網友回復:
因為 用 定時器 移動 小球時 ,不需要 重繪 整個 rect ,所以 RGN 是 上次 球 位置 與 這次 球的 不 重疊 部分。
void CDesktopRectRefreshDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
static BOOL bmove=FALSE;
static int inc=1;
if(m_rc.right >= m_maxWid) inc=-1;
else if(m_rc.left <0) inc= 1;
//
bmove=!bmove;
if(bmove)
{// draw rect
m_rc.OffsetRect(inc,0);// x only
ReFreshDesktopRect(&m_rc,0,TRUE);
}
else
{// erase rgn
CRect rc=m_rc;
rc.InflateRect(2,2);
HRGN hrgnc=CreateEllipticRgn(rc.left, rc.top, rc.right, rc.bottom);
HRGN hrgnb=CreateEllipticRgn(m_rc.left, m_rc.top, m_rc.right, m_rc.bottom);
CombineRgn(hrgnc,hrgnc,hrgnb,RGN_XOR);
ReFreshDesktopRect(0,hrgnc,FALSE);
DeleteObject(hrgnc);
}
//
CDialog::OnTimer(nIDEvent);
}
注意 CombineRgn(hrgnc,hrgnc,hrgnb,RGN_XOR);
uj5u.com熱心網友回復:
我測驗的設定透明有效呢
void myDrawText(HDC hdc, int x, int y, LPCTSTR szTxt, COLORREF txtColor)
{
int nSaveDC = SaveDC(hdc);
COLORREF txColor = SetTextColor(hdc, txtColor);
int iBkMode = SetBkMode(hdc, TRANSPARENT);
ExtTextOut(hdc, x, y, 0,
NULL, szTxt, _tcslen(szTxt), NULL);
SetBkMode(hdc, iBkMode);
SetTextColor(hdc, txColor);
RestoreDC(hdc, nSaveDC);
}
uj5u.com熱心網友回復:
主要可能是跟HDC有關,我用的是GetDesktopWindow(),你用的是函式傳入的HDC,你可以嘗試將GetDesktopWindow() 傳入看是否有問題。
我用spy 找了個mspaint.exe 的客戶區,文字透明,重繪也基本符合預期。
但是一旦使用GetDesktopWindow()則還是老樣子。
uj5u.com熱心網友回復:
win7 桌面 右擊 點“個性化”uj5u.com熱心網友回復:
不知何意?
uj5u.com熱心網友回復:
可能 與 DWM 有關 。搜索 “Windows Vista for Developers——第三部分:桌面視窗管理器”(Desk Window Manager)uj5u.com熱心網友回復:
看了半天那個文章,實在是MFC部分缺失太多。本意只是在螢屏上繪制一個易失的方框以及標題。結果死活不透明。可否有簡單的方法解決。麻煩幫忙研究一下下,謝謝!實在文字背景透明問題無法解決。可否有簡單的重繪解決方法。麻煩您了!
uj5u.com熱心網友回復:
百度搜相關關鍵字。uj5u.com熱心網友回復:
void CxxxDlg::OnButton2(){
CWnd *pWinDesk=GetDesktopWindow();
CDC *pDC=pWinDesk->GetWindowDC();
// GetTextExtentPoint32(pDC->m_hDC,"Hello World!")
pDC->SetBkMode(TRANSPARENT);
pDC->SetTextColor(RGB(255,0,255));
CRect rc(0,0,200,30);
pDC->ExtTextOut(0,0,ETO_CLIPPED, &rc,"Hello World!",12,0);
}
沒問題 !
uj5u.com熱心網友回復:
勉強可以:
void CDirDDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
HWND hWndDesk = ::GetDesktopWindow();
if(hWndDesk==0)
{
afxDump << "Failed\n";
return;
}
// erase old,
CRect rcErase(m_old.x,m_old.y,m_old.x+120,m_old.y+20);//
::RedrawWindow(hWndDesk,&rcErase, 0, RDW_ERASE | RDW_UPDATENOW | RDW_INVALIDATE | RDW_ALLCHILDREN);// 1 4 80 =0x85);
// update
m_old=point;
// CDialog::OnLButtonDown(nFlags, point);
}
void CDirDDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
HWND hWndDesk = ::GetDesktopWindow();
if(hWndDesk==0)
{
afxDump << "Failed\n";
return;
}
HDC hDC=::GetWindowDC(hWndDesk);
CRect rcDraw(m_old.x,m_old.y,m_old.x+120,m_old.y+30);//
CString str;
str.Format(_T("[%4d,%4d] "),point.x,point.y);
// afxDump << str << "\n";
::SetBkMode(hDC,TRANSPARENT);
::SetTextColor(hDC, RGB(255, 0, 0));
// out newpos
::TextOut(hDC,point.x,point.y,str,str.GetLength());
::ReleaseDC( hWndDesk,hDC);
//
// CDialog::OnLButtonUp(nFlags, point);
}
uj5u.com熱心網友回復:
請問您這個程式的運行環境是什么? OS?
uj5u.com熱心網友回復:
win7 vc6uj5u.com熱心網友回復:
用win7 實驗了一下,背景色不是黑的,是desktop的背景,也就是說,如果螢屏只顯示desktop則是文字透明的。如果螢屏上有其他視窗,背景色為desktop畫面。
uj5u.com熱心網友回復:
注意 ::RedrawWindow 需要至少 10ms 執行時間,所以 使用 在 MouseMove 中時 ,當前程式要 Sleep(10)uj5u.com熱心網友回復:
不建議在桌面直接繪制,只要隨便重繪一次,你的東西就丟了。正常的視窗 WM_PAINT 中繪制不會重疊,因為還有 WM_ERASEBKGND 擦掉之前東西。如果自己繪制東西還不想重疊,那就只能保存對應區域的背景,然后每次先把自己文字繪制到背景,然后再把背景整塊繪制上去。uj5u.com熱心網友回復:
你這個10ms倒是提醒我了。其實redraw不redraw只是衍生問題。最主要的是exttextout輸出背景不透明。我曾經在vs的vb.net中,用api重現程式,結果也是一樣。
現在看來,仍舊有鴻溝啊。改天裝個vc試一試。
uj5u.com熱心網友回復:
我做的并不是視窗程式,只是一個截圖并且簡單ocr的程式,顯示個框,主要是程式運行的時候,檢查引數正確性而已。只要閃現一下下就可以了。實際上我并不像保持螢屏上一直顯示那個框和文字。
因為截圖使用的是winapi,所以,順勢用api寫了個畫框和寫文字的代碼。事實上,你這種方式反對我的程式有影響,比如我在螢屏上截圖的是一個流逝的時間,我保存并畫回去,反倒影響了ocr出來時間的真實性。
uj5u.com熱心網友回復:
關鍵是 RDW_ALLCHILDREN因為 hWndDesk=::GetDesktopWindow(); 即 #32769 (桌面)
不是 桌面當前 視窗, 桌面 顯示的視窗 是 "SysListView32","FolderView"
所以 桌面的 重繪 有 很多 子視窗 !需要 時間 ,
因此 重繪 和 重繪 ,不要在 一個 回應 中 (如 up 和 down)
至于 你說的 ExtTextOut 并沒有 問題 !
// out newpos
::ExtTextOut(hDC,point.x,point.y,0,NULL,str,str.GetLength(),NULL);
// ::TextOut(hDC,point.x,point.y,str,str.GetLength());
uj5u.com熱心網友回復:
A lovely goldfish desktop pet (using alpha-PNG and GDI+) http://www.codeproject.com/Articles/29184/A-lovely-goldfish-desktop-pet-using-alpha-PNG-anduj5u.com熱心網友回復:
這是個不錯的思路,回頭我做2個函式,多重繪幾次試一試。
最近改動程式發現,畫圖完畢后,做一次截圖,文字背景有幾率為透明,具體沒詳細測驗。先謝過,回頭測驗完畢后再通報結果。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/70009.html
標籤:界面
