用winapi 写了个桌面 画框写文字的程序,除了问题。不知道这里有没有人能指导一下!

时间:2022-05-06 14:20:50
最近写了个截屏的程序,但是没有屏幕显示,就想着在屏幕上标记个框框啥的。有鉴于此,写了下面的的代码。
然而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的文字?

6 个解决方案

#1


上次写的 内容 必须 清除。
那个 矩形区必须 Invalidate ,让 桌面 重绘!

#2


填充背景 重新绘制字体
不能擦除的色块是指光标么? 试试 HideCaret SetCaretPos 再 ShowCaret

#3


引用 1 楼 schlafenhamster 的回复:
上次写的 内容 必须 清除。
那个 矩形区必须 Invalidate ,让 桌面 重绘!


理论上我知道,实际上搞不清楚重绘的过程,能不能给点代码?
我在函数最前面加了
	
        # 重绘窗口
hwnd=win32gui.GetDesktopWindow()
win32gui.RedrawWindow(hwnd,(1000,300,1400,700),0,win32con.RDW_UPDATENOW)
print("RedrawWindow getlasterror",win32api.GetLastError())

hwndDC=win32gui.GetWindowDC(hwnd)

没有效果啊!!!!

#4


引用 2 楼 zgl7903 的回复:
填充背景 重新绘制字体
不能擦除的色块是指光标么? 试试 HideCaret SetCaretPos 再 ShowCaret


ExtTextOut绘制在屏幕上的字体总是带有背景颜色啊!

#5


用winapi 写了个桌面 画框写文字的程序,除了问题。不知道这里有没有人能指导一下!
用winapi 写了个桌面 画框写文字的程序,除了问题。不知道这里有没有人能指导一下!
矩形倒是空心的。但是文字总有背景色。其实说背景色并不准确,如果SetBkMode设置的不是透明,设置O开头的那个参数,则背景色是灰色,设置透明则是黑色。

ps:
我在这个函数后面加了个获取DC并截图的代码,整个程序执行2遍,第三遍文字背景就透明了,只是文字照样重叠。。。疯了我。。。。

#6


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;
}



#1


上次写的 内容 必须 清除。
那个 矩形区必须 Invalidate ,让 桌面 重绘!

#2


填充背景 重新绘制字体
不能擦除的色块是指光标么? 试试 HideCaret SetCaretPos 再 ShowCaret

#3


引用 1 楼 schlafenhamster 的回复:
上次写的 内容 必须 清除。
那个 矩形区必须 Invalidate ,让 桌面 重绘!


理论上我知道,实际上搞不清楚重绘的过程,能不能给点代码?
我在函数最前面加了
	
        # 重绘窗口
hwnd=win32gui.GetDesktopWindow()
win32gui.RedrawWindow(hwnd,(1000,300,1400,700),0,win32con.RDW_UPDATENOW)
print("RedrawWindow getlasterror",win32api.GetLastError())

hwndDC=win32gui.GetWindowDC(hwnd)

没有效果啊!!!!

#4


引用 2 楼 zgl7903 的回复:
填充背景 重新绘制字体
不能擦除的色块是指光标么? 试试 HideCaret SetCaretPos 再 ShowCaret


ExtTextOut绘制在屏幕上的字体总是带有背景颜色啊!

#5


用winapi 写了个桌面 画框写文字的程序,除了问题。不知道这里有没有人能指导一下!
用winapi 写了个桌面 画框写文字的程序,除了问题。不知道这里有没有人能指导一下!
矩形倒是空心的。但是文字总有背景色。其实说背景色并不准确,如果SetBkMode设置的不是透明,设置O开头的那个参数,则背景色是灰色,设置透明则是黑色。

ps:
我在这个函数后面加了个获取DC并截图的代码,整个程序执行2遍,第三遍文字背景就透明了,只是文字照样重叠。。。疯了我。。。。

#6


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;
}