- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想创建一个形状不规则/蒙皮的窗口(目前只有圆角、alpha 混合角)。创建顶级窗口后,我正在处理 WM_CREATE 消息并执行以下操作:
稍后我计划通过设置 alpha channel 并预乘相关位来实现边缘的圆化。
现在,如果我在窗口中创建一个按钮,它不会自行呈现。我知道为什么,并且我正在努力想出一个优雅的解决方案来在这里制作我的自定义控件(子窗口)。
我最初的方法是首先放弃使用子窗口,让顶层窗口完成所有绘图以及输入处理、 HitTest 等。我发现这太乏味了,相反我想让 Windows 为我处理所有这些。
现在,我知道如果我创建一个子窗口,它当然会正常运行(例如对用户输入使用react),我想利用它。我计划通常使用 CreateWindowEx() 创建子窗口(自定义控件),以便它们获得窗口句柄并接收窗口消息,而不必担心手动传递它们。
我需要以某种方式绘制这些窗口,据我所知,唯一可能的方法是使用绘制整个顶级窗口的例程。我需要发明某种逻辑来让顶层窗口的绘制例程在必要时绘制我的子窗口。据我了解,UpdateLayeredWindow() 函数需要重绘整个窗口。
例如,让子控件呈现自己的图像并发送到顶层窗口的绘制例程是否明智?例如,子窗口将用户 WM 发送到顶层窗口,将指向其渲染位图的指针作为 WPARAM 传递,并将指向定义其位置和大小的结构的指针作为 LPARAM。
有什么更好的主意吗?这有任何意义吗?
谢谢,埃里克
最佳答案
我正在尝试做一件非常相似的事情。从阅读这个和其他搜索网络。它将用于绘制 CWnd(或 HWND)的推荐机制和它的子级连接到您自己的 CDC(或 HDC)上,即使用打印 API。
CWnd 具有 Print 和 PrintClient 方法,它们可以正确发送 WM_PRINT。还有 Win32 方法:PrintWindow。
起初我很难让它工作,但我最终找到了正确的方法和参数。对我有用的代码是:
void Vg2pImageHeaderRibbon::Update() {
// Get dimensions
CRect window_rect;
GetWindowRect(&window_rect);
// Make mem DC + mem bitmap
CDC* screen_dc = GetDC(); // Get DC for the hwnd
CDC dc;
dc.CreateCompatibleDC(screen_dc);
CBitmap dc_buffer;
dc_buffer.CreateCompatibleBitmap(screen_dc, window_rect.Width(), window_rect.Height());
auto hBmpOld = dc.SelectObject(dc_buffer);
// Create a buffer for manipulating the raw bitmap pixels (per-pixel alpha).
// Used by ClearBackgroundAndPrepForPerPixelTransparency and CorrectPerPixelAlpha.
BITMAP raw_bitmap;
dc_buffer.GetBitmap(&raw_bitmap);
int bytes = raw_bitmap.bmWidthBytes * raw_bitmap.bmHeight;
std::unique_ptr<char> bits(new char[bytes]);
// Clears the background black (I want semi-transparent black background).
ClearBackgroundAndPrepForPerPixelTransparency(dc, raw_bitmap, bytes, bits.get(), dc_buffer);
// To get the window and it's children to draw using print command
Print(&dc, PRF_CLIENT | PRF_CHILDREN | PRF_OWNED);
CorrectPerPixelAlpha(dc, raw_bitmap, bytes, bits.get(), dc_buffer);
// Call UpdateLayeredWindow
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
CPoint ptSrc;
UpdateLayeredWindow(
screen_dc,
&window_rect.TopLeft(),
&window_rect.Size(),
&dc,
&ptSrc,
0,
&blend,
ULW_ALPHA
);
SelectObject(dc, hBmpOld);
DeleteObject(dc_buffer);
ReleaseDC(screen_dc);
}
这对我有用。但是万一你的窗口或 child 不支持 WM_PRINT 我查看了它是如何为 CView 类实现的,我发现这个类提供了一个名为 OnDraw(CDC* dc) 的虚拟方法,它提供了一个 DC 来绘制。 WM_PAINT 是这样实现的:
CPaintDC dc(this);
OnDraw(&dc);
并且实现了 WM_PAINT:
CDC* dc = CDC::FromHandle((HDC)wParam);
OnDraw(dc);
所以 WM_PAINT 和 WM_PRINT 结果是一个 OnDraw(),并且绘图代码实现了一次。
您基本上可以将相同的逻辑添加到您自己的 CWnd 派生类中。这可能无法使用 visual studio 的类向导。我必须将以下内容添加到消息映射 block :
BEGIN_MESSAGE_MAP(MyButton, CButton)
...other messages
ON_MESSAGE(WM_PRINT, OnPrint)
END_MESSAGE_MAP()
还有我的处理程序:
LRESULT MyButton::OnPrint(WPARAM wParam, LPARAM lParam) {
CDC* dc = CDC::FromHandle((HDC)wParam);
OnDraw(dc);
return 0;
}
注意:如果您在已经自动支持此功能的类上添加自定义 WM_PRINT 处理程序,那么您将失去默认实现。 OnPrint 没有 CWnd 方法,因此您必须使用 Default() 方法来调用默认处理程序。
我还没有尝试过以下方法,但我希望它能起作用:
LRESULT MyCWnd::OnPrint(WPARAM wParam, LPARAM lParam) {
CDC* dc = CDC::FromHandle((HDC)wParam);
// Do my own drawing using custom drawing
OnDraw(dc);
// And get the default handler to draw children
return Default();
}
上面我定义了一些奇怪的方法:ClearBackgroundAndPrepForPerPixelTransparency 和 CorrectPerPixelAlpha。这些允许我在让子控件完全不透明时将对话框的背景设置为半透明(这是我的每像素透明度)。
// This method is not very efficient but the CBitmap class doens't
// give me a choice I have to copy all the pixel data out, process it and set it back again.
// For performance I recommend using another bitmap class
//
// This method makes every pixel have an opacity of 255 (fully opaque).
void Vg2pImageHeaderRibbon::ClearBackgroundAndPrepForPerPixelTransparency(
CDC& dc, const BITMAP& raw_bitmap, int bytes, char* bits, CBitmap& dc_buffer
) {
CRect rect;
GetClientRect(&rect);
dc.FillSolidRect(0, 0, rect.Width(), rect.Height(), RGB(0,0,0));
dc_buffer.GetBitmapBits(bytes, bits);
UINT* pixels = reinterpret_cast<UINT*>(bits);
for (int c = 0; c < raw_bitmap.bmWidth * raw_bitmap.bmHeight; c++ ){
pixels[c] |= 0xff000000;
}
dc_buffer.SetBitmapBits(bytes, bits);
}
// This method is not very efficient but the CBitmap class doens't
// give me a choice I have to copy all the pixel data out, process it and set it back again.
// For performance I recommend using another bitmap class
//
// This method modifies the opacity value because we know GDI drawing always sets
// the opacity to 0 we find all pixels that have been drawn on since we called
// For performance I recommend using another bitmap class such as the IcfMfcRasterImage
// ClearBackgroundAndPrepForPerPixelTransparency. Anything that has been drawn on will get an
// opacity of 255 and all untouched pixels will get an opacity of 100.
void Vg2pImageHeaderRibbon::CorrectPerPixelAlpha(
CDC& dc, const BITMAP& raw_bitmap, int bytes, char* bits, CBitmap& dc_buffer
) {
const unsigned char AlphaForBackground = 100; // (0 - 255)
const int AlphaForBackgroundWord = AlphaForBackground << 24;
dc_buffer.GetBitmapBits(bytes, bits);
UINT* pixels = reinterpret_cast<UINT*>(bits);
for (int c = 0; c < raw_bitmap.bmWidth * raw_bitmap.bmHeight; c++ ){
if ((pixels[c] & 0xff000000) == 0) {
pixels[c] |= 0xff000000;
} else {
pixels[c] = (pixels[c] & 0x00ffffff) | AlphaForBackgroundWord;
}
}
dc_buffer.SetBitmapBits(bytes, bits);
}
这是我的测试应用程序的屏幕截图。当用户将鼠标悬停在“更多按钮”按钮上时,将创建具有半透明背景的对话框。按钮“B1”到“B16”是从 CButton 派生的子控件,使用上面显示的 Print() 调用绘制。您可以在 View 的右侧边缘和按钮之间看到半透明背景。
关于c++ - 创建带有子窗口(控件)的分层窗口的策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7981322/
我有这个 html 代码: HELLO WORLD! X V HELLO WORLD! X V 我想按 X(类关闭)将父 div 的高度更改为 20px 并显示 V(类打开),但在每个 d
在会计应用程序的许多不同实现中,有两种主要的数据库设计方法来保存日志和分类帐数据。 只保留 Journal 信息,然后 Ledger 只是 Journal 的一个 View (因为 journal 总
我想在另一个子里面有一个子, sub a { sub b { } } 我想为每次调用 sub b 创建一个新的 sub a 实例。有没有办法在 Perl 中做到这一点? 当我运行上面的
我有一些代码正在查找重复项并突出显示单元格: Private Sub cmdDups_Click() Dim Rng As Range Dim cel As Range Set Rng = ThisW
可能有一个简单的解决方案,但我很难过。 我有一个包含一个 ID 字段的主表。在两个可能的字段中有一个具有该 ID 的子表。想象一个由选手 A 和选手 B 组成的 double 队。Master 表将有
假设我有一个包含对象的数组: [ { "id": "5a97e047f826a0111b754beb", "name": "Hogwarts", "parentId": "
我正在尝试对 MySQL 数据库表执行一对父/子模型的批量插入,但似乎无法使用标准的 ActiveRecord 功能来完成。所以,我尝试了 activerecord-import gem,但它也不支持
我有一个带有多个子类的父抽象类。最终,我希望通过 GUI 中的进度条显示子类中完成的进度。 我目前所做的,我意识到这是行不通的,是在父类中声明为每个子类将覆盖的虚拟方法的事件方法定义。所以像: pub
是否可以通过键数组在对象中设置变量?例如我有这个对象: var obj = {'outer': {'inner': 'value'} }; 并希望设置由键数组选择的值: var keys = ['ou
我有一个名为 companies 的 MySQL 表,如下所示: +---------+-----------+-----------+ | id_comp | comp_name | id_pare
我正在尝试使用 sublime text 在 sublime text 上的 ionic 上打开我的第一个应用程序。它给了我一个“找不到命令”的错误。如何修复? 我试过这些命令: sudo rm -r
不好意思问,但我正在使用 webapp2,我正在设计一个解决方案,以便更容易定义路由 based on this google webapp2 route function .但这完全取决于能够在子级
我有代表树的数字字符串(我不知道是否有官方名称): 012323301212 上面的例子代表了 2 棵树。根用 0 表示。根的直接子代为“1”,“1”的直接子代为“2”,依此类推。我需要将它们分组到由
是否可以在当前 Activity 之上添加 Activity 。例如,假设我单击一个按钮,然后它将第二个 Activity 添加到当前 Activity 。而第二个 Activity 只覆盖了我当前
我很难思考如何为子资源建模。 以作者的书籍为例。你可以有 N 本书,每本书只有一位作者。 /books GET /books POST /books/id PUT /books/id DELETE 到
有人可以向我解释以下内容(python 2.7) 来自已解析文件的两个字符串数字: '410.9''410.9 '(注意尾随空格) A_LIST = ['410.9 '] '410.9' in '41
背景 在 PowerShell 中构建 hash table 是很常见的通过特定属性快速访问对象,例如以 LastName 为基础建立索引: $List = ConvertFrom-Csv @' I
我真的很难弄清楚如何调用嵌套 Polymer Web 组件的函数。 这是标记: rise-distribution组件有 canPlay我想从 rise-playlist
我写了一个小工具转储(以 dot 格式)一个项目的依赖关系图,其中所有位于同一目录中的文件都聚集在一个集群中。当我尝试生成包含相应图形的 pdf 时,dot开始哭: 命令 dot -Tpdf trim
给定一个 CODE ref,是否可以: 访问该 CODE ref 的解析树 通过指定 CODE ref 的解析树来创建一个新的 CODE ref,该解析树可以包含在 1 中返回的解析树的元素 通常我们
我是一名优秀的程序员,十分优秀!