如何解决RTL窗口上的PrintWindow生成带有PW_RENDERFULLCONTENT标志的镜像图像
我正在尝试使用以下使用pywin32的python代码获取RTL窗口的图像:
def get_window_image(hwnd: int,window_region: Region) -> np.ndarray:
PW_RENDERFULLCONTENT = 2
dc_handle = None
dc_obj = None
save_bitmap = None
memory_dc_obj = None
try:
# Creating device context for retrieving the screenshot. Based on the following:
# https://stackoverflow.com/questions/19695214/python-screenshot-of-inactive-window-printwindow-win32gui
# Documentation about device context:
# https://docs.microsoft.com/en-us/cpp/mfc/device-contexts?view=vs-2019
dc_handle = win32gui.GetWindowDC(hwnd)
dc_obj = win32ui.CreateDCFromHandle(dc_handle)
memory_dc_obj = dc_obj.CreateCompatibleDC()
# Create a bitmap from the device context
save_bitmap = win32ui.CreateBitmap()
save_bitmap.CreateCompatibleBitmap(dc_obj,window_region.get_width(),window_region.get_height())
memory_dc_obj.SelectObject(save_bitmap)
if sys.getwindowsversion().major >= 8:
render_flags = PW_RENDERFULLCONTENT
else:
render_flags = 0
# Take a screenshot of the window
windll.user32.PrintWindow(hwnd,memory_dc_obj.GetSafeHdc(),render_flags)
# Retrieve the bitmap content from the taken screenshot
bmp_info = save_bitmap.GetInfo()
bmp_str = save_bitmap.GetBitmapBits(True)
bmp_height,bmp_width = bmp_info['bmHeight'],bmp_info['bmWidth']
window_image = np.fromstring(string=bmp_str,dtype=np.uint8)
window_image = window_image.reshape((bmp_height,bmp_width,4))
window_image[:,:,3] = 255 # remove alpha channel
return window_image
finally:
if save_bitmap is not None:
win32gui.DeleteObject(save_bitmap.GetHandle())
if memory_dc_obj is not None:
memory_dc_obj.DeleteDC()
if dc_obj is not None:
dc_obj.DeleteDC()
if dc_handle is not None:
win32gui.ReleaseDC(hwnd,dc_handle)
生成RTL窗口的代码:
win32gui.MessageBox(None,'משהו בעברית','test-rtl',win32con.MB_ICONWARNING | win32con.MB_RTLREADING)
我正在传递PrintWindow
标志-PW_RENDERFULLCONTENT = 2
,这应该有助于使用正确的框架而不是经典框架来渲染窗口(另请参见https://stackoverflow.com/a/40042587/4313487)
我有2台具有相同规格的PC。在第一台PC上,图像以镜像方式打印,在第二台PC上,图像以原始显示的方式打印。
两台PC的Windows 10都具有相同的区域和区域设置。在两台PC上,消息框窗口具有相同的样式标志,包括WS_EX_LAYOUTRTL。
来自PC1的图像-被镜像:
来自PC2的图像(相同代码):
当传递给PrintWindow的标志为0(而不是PW_RENDERFULLCONTENT)时,图像将在两台PC上镜像:
为什么会发生?
如何确保在不同PC上以相同方向打印图像?
解决方法
如果不建议使用。什么是最好的打印方式 窗口应用程序(例如铬),如果没有此标志,则该应用程序是 呈现为黑屏?
我使用PrintWindow
(无PW_RENDERFULLCONTENT
)来打印chrome窗口,如果没有最小化chrome窗口,则没有黑屏问题。话虽如此,Chrome在过去很长一段时间内都返回黑屏存在很多问题。
但是PrintWindow()
不能很好地工作。您可以从该DC尝试GetWindowDC()
和BitBlt()
到您的位图中。或GetClientRect()+ClientToScreen()
和BitBlt()
从屏幕DC到位图的矩形。
或者查看Win10中添加的Screen Capture API。或在Win8中添加的Desktop Duplication API。或Direct3D
。参见Ways to capture the screen。
引用:Getting Black Screenshots with Windows API
由于您需要在python中实现它,因此建议您使用第一种方法(相对简单)GetClientRect()+ClientToScreen() and BitBlt()...
代码示例:Capturing screenshots with win32api python returns black image