- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
介绍和相关信息:
我有一个复杂的绘画要在我的主窗口的 WM_PAINT 处理程序中实现。
我已经提交了下面的图片来说明它:
主窗口具有静态控件,而不是具有 SS_NOTIFY
样式的按钮。
当用户点击它们时,程序中会发生某些操作,这些操作目前无关紧要。
下图显示了主窗口中静态控件的位置:
橙色面板上的 map 是一个 EMF
文件,左上角和右上角的 logo 是 PNG
文件,其他图片是 bitmap
s。Visual Styles
通过 #pragma
指令启用。我还使用 GDI+
和 GDI
。
项目被创建为空项目,我已经从“头”开始编码了所有内容。
为了实现这个任务,我决定在 WM_PAINT
中绘制 整张图片,并在 将透明的 static control
s 放在与它们对应的图片 上。
为了保持我的代码干净和简单,我制作了实现上述功能的函数,因此我的 WM_PAINT
处理程序可以尽可能小。
更新 #1(2013 年 12 月 17 日更新):
为了实现从成员 arx 获得的建议,我发布了一个可以编译并且可以重现问题的源代码:
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <gdiplus.h>
#pragma comment( linker, "/manifestdependency:\"type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' \
language='*'\"" )
#pragma comment( lib, "comctl32.lib")
#pragma comment( lib, "Msimg32.lib" )
#pragma comment( lib, "Gdiplus.lib" )
using namespace Gdiplus;
// variable for storing the instance
static HINSTANCE hInst;
// variables for painting the window
static HBRUSH hbPozadina, // gray background brush for grid on the top
BlueFrame, // needed to frame blue static controls
hbr; // orange brush for orange panel
/********* helper functions for WM_PAINT **********/
// Fills triangle with gradient brush
void GradientTriangle( HDC MemDC,
LONG x1, LONG y1,
LONG x2, LONG y2,
LONG x3, LONG y3,
COLORREF top, COLORREF bottom )
{
TRIVERTEX vertex[3];
vertex[0].x = x1;
vertex[0].y = y1;
vertex[0].Red = GetRValue(bottom) << 8;
vertex[0].Green = GetGValue(bottom) << 8;
vertex[0].Blue = GetBValue(bottom) << 8;
vertex[0].Alpha = 0x0000;
vertex[1].x = x2;
vertex[1].y = y2;
vertex[1].Red = GetRValue(top) << 8;
vertex[1].Green = GetGValue(top) << 8;
vertex[1].Blue = GetBValue(top) << 8;
vertex[1].Alpha = 0x0000;
vertex[2].x = x3;
vertex[2].y = y3;
vertex[2].Red = GetRValue(bottom) << 8;
vertex[2].Green = GetGValue(bottom) << 8;
vertex[2].Blue = GetBValue(bottom) << 8;
vertex[2].Alpha = 0x0000;
// Create a GRADIENT_TRIANGLE structure that
// references the TRIVERTEX vertices.
GRADIENT_TRIANGLE gTriangle;
gTriangle.Vertex1 = 0;
gTriangle.Vertex2 = 1;
gTriangle.Vertex3 = 2;
// Draw a shaded triangle.
GradientFill( MemDC, vertex, 3, &gTriangle, 1, GRADIENT_FILL_TRIANGLE);
}
// draws the background for the part of the window between header and footer
void drawBackground( HDC MemDC, RECT r )
{
/******* main window's gradient background ********/
GradientTriangle( MemDC, r.right, r.bottom - r.top - 30,
r.left, r.bottom - r.top - 30,
r.left, r.top + 120,
RGB( 0x95, 0xB3, 0xD7 ),
RGB( 0xDB, 0xE5, 0xF1 ) );
GradientTriangle( MemDC, r.right, r.bottom - r.top - 30,
r.right, r.top + 120,
r.left, r.top + 120,
RGB( 0x95, 0xB3, 0xD7 ),
RGB( 0xDB, 0xE5, 0xF1 ) );
}
// draws the header of the main window
void drawHeader( HDC MemDC, RECT rect, HBRUSH hbPozadina )
{
FillRect( MemDC, &rect, hbPozadina );
}
// fills rectangle with gradient brush
void GradientRectangle( HDC MemDC,
LONG x1, LONG y1,
LONG x2, LONG y2,
COLORREF top,
COLORREF bottom )
{
// vertexes for static's gradient color
TRIVERTEX vertexS[2];
vertexS[0].x = x1;
vertexS[0].y = y1;
vertexS[0].Red = GetRValue(top) << 8;
vertexS[0].Green = GetGValue(top) << 8;
vertexS[0].Blue = GetBValue(top) << 8;
vertexS[0].Alpha = 0x0000;
vertexS[1].x = x2;
vertexS[1].y = y2;
vertexS[1].Red = GetRValue(bottom) << 8;
vertexS[1].Green = GetGValue(bottom) << 8;
vertexS[1].Blue = GetBValue(bottom) << 8;
vertexS[1].Alpha = 0x0000;
// Create a GRADIENT_RECT structure that
// references the TRIVERTEX vertices.
GRADIENT_RECT gRect;
gRect.UpperLeft = 0;
gRect.LowerRight = 1;
// Draw a shaded rectangle.
GradientFill( MemDC, vertexS, 2, &gRect, 1, GRADIENT_FILL_RECT_V );
}
// fills the "button" with blue gradient and frames it with blue brush
void FillButton( HDC MemDC, RECT rect, HBRUSH BlueFrame )
{
// fill upper half of the rectangle
GradientRectangle( MemDC,
rect.left, rect.top,
rect.right, rect.top + ( rect.bottom - rect.top ) / 2,
RGB( 0x95, 0xB3, 0xD7 ),
RGB( 0x4F, 0x8B, 0xBD ) );
// fill bottom half of the rectangle
GradientRectangle( MemDC,
rect.left, rect.top + ( rect.bottom - rect.top ) / 2,
rect.right, rect.bottom,
RGB( 0x4F, 0x8B, 0xBD ),
RGB( 0x95, 0xB3, 0xD7 ) );
FrameRect( MemDC, &rect, BlueFrame );
}
// draws the "status bar" at the bottom of the main window
void drawFooter( HDC MemDC, RECT r, COLORREF top, COLORREF bottom )
{
// down triangle
GradientTriangle( MemDC,
r.right, r.bottom,
( r.right - r.left ) / 2,
r.bottom - r.top - 15,
r.left, r.bottom,
top, bottom );
// upper triangle
GradientTriangle( MemDC,
r.right, r.bottom - r.top - 30,
( r.right - r.left ) / 2, r.bottom - r.top - 15,
r.left, r.bottom - r.top - 30,
top, bottom );
// left triangle
GradientTriangle( MemDC,
r.left, r.bottom,
( r.right - r.left ) / 2, r.bottom - r.top - 15,
r.left, r.bottom - r.top - 30,
top, bottom );
// right triangle
GradientTriangle( MemDC,
r.right, r.bottom - r.top - 30,
( r.right - r.left ) / 2, r.bottom - r.top - 15,
r.right, r.bottom,
top, bottom );
}
// draw orange panel on which map and 3 static controls will be drawn
void drawOrangePanel( HDC MemDC, RECT r, COLORREF top, COLORREF bottom )
{
// down triangle
GradientTriangle( MemDC,
r.right, r.bottom,
r.left + ( r.right - r.left ) / 2,
r.top + ( r.bottom - r.top ) / 2,
r.left, r.bottom,
top, bottom );
// upper triangle
GradientTriangle( MemDC,
r.right, r.top,
r.left + ( r.right - r.left ) / 2,
r.top + ( r.bottom - r.top ) / 2,
r.left, r.top,
top, bottom );
// left triangle
GradientTriangle( MemDC,
r.left, r.bottom,
r.left + ( r.right - r.left ) / 2,
r.top + ( r.bottom - r.top ) / 2,
r.left, r.top,
top, bottom );
// right triangle
GradientTriangle( MemDC,
r.right, r.top,
r.left + ( r.right - r.left ) / 2,
r.top + ( r.bottom - r.top ) / 2,
r.right, r.bottom,
top, bottom );
}
void onPaint( HWND hwnd, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint( hwnd, &ps);
RECT r; // rectangle for main window's client area
GetClientRect( hwnd, &r);
HDC MemDC = CreateCompatibleDC(hdc); // back buffer
// compatible bitmap for MemDC
HBITMAP bmp = CreateCompatibleBitmap( hdc, r.right - r.left, r.bottom - r.top ),
oldBmp = (HBITMAP)SelectObject( MemDC, bmp ); // needed for cleanup
// draw background for middle part of the window
drawBackground( MemDC, r );
// draw header with grid lines
RECT rect; // position it properly at the top
rect.left = r.left;
rect.top = r.top;
rect.right = r.right;
rect.bottom = 120;
drawHeader( MemDC, rect, hbPozadina );
// draw "status bar"
drawFooter( MemDC, r, RGB( 0x48, 0xAC, 0xC6), RGB( 0x31, 0x83, 0x99 ) );
/******* draw static control's background ****/
//======== top left static control ======//
//position it properly
rect.left = ( 3 * ( r.right - r.left ) / 4 - 340 ) / 3;
rect.top = 120 + ( r.bottom - r.top - 450 ) / 3;
rect.right = 150 + ( 3 * ( r.right - r.left ) / 4 - 340 ) / 3;
rect.bottom = 270 + ( r.bottom - r.top - 450 ) / 3;
// draw gradient button
FillButton( MemDC, rect, BlueFrame );
//======================== draw orange panel =================//
//position it properly
rect.left = 3 * ( r.right - r.left ) / 4 - 40;
rect.top = r.top + 140;
rect.right = rect.left + ( r.right - r.left ) / 4;
rect.bottom = rect.top + ( r.bottom - r.top - 190 );
drawOrangePanel( MemDC, rect, RGB( 0xFF, 0xC8, 0xAA ), RGB( 0xFF, 0x96, 0x48 ) );
/****** draw back buffer on the screen DC *******/
BitBlt( hdc, 0, 0, r.right - r.left, r.bottom - r.top, MemDC, 0, 0, SRCCOPY );
/************** cleanup *******************/
SelectObject( MemDC, oldBmp );
DeleteObject(bmp); // compatible bitmap for MemDC
DeleteDC(MemDC);
EndPaint( hwnd, &ps);
}
// WinMain's procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
//******** brushes ***********//
// load gray background brush for the top banner
hbPozadina = CreateSolidBrush( RGB( 230, 230, 230 ) );
// brush for orange panel that holds 3 static controls and a map
hbr = CreateSolidBrush( RGB( 255, 163, 94 ) );
// blue frame for blue static controls
BlueFrame = CreateSolidBrush( RGB(79, 129, 189) );
/*******************************************/
}
return (LRESULT)0;
case WM_ERASEBKGND:
return (LRESULT)1; // so we avoid flicker ( all painting is in WM_PAINT )
case WM_PAINT:
{
// paint the picture
onPaint( hwnd, wParam, lParam );
}
return (LRESULT)0;
case WM_SIZE:
InvalidateRect( hwnd, NULL, FALSE );
return (LRESULT)0;
case WM_CLOSE:
// destroy brushes
DeleteObject(hbPozadina);
DeleteObject(hbr);
DeleteObject(BlueFrame);
DestroyWindow(hwnd);
return (LRESULT)0;
case WM_DESTROY:
PostQuitMessage(0);
return (LRESULT)0;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
// WinMain
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow)
{
// store hInstance in global variable for later use
hInst = hInstance;
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
/**** variables for GDI+ initialization ******/
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
/********* Initialize GDI+. ********/
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
/**** finished GDI+ initialisation *****/
// initialize common controls
INITCOMMONCONTROLSEX iccex;
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
iccex.dwICC = ICC_STANDARD_CLASSES ;
InitCommonControlsEx(&iccex);
// register main window class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = NULL;//(HBRUSH)GetStockObject( WHITE_BRUSH );
wc.lpszMenuName = NULL;
wc.lpszClassName = L"Main_Window";
wc.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox( NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK );
return 0;
}
// create main window
hwnd = CreateWindowEx( 0, // WS_EX_COMPOSITED "improved" drawing of the edges
L"Main_Window",
L"Геотермист",
WS_OVERLAPPEDWINDOW,
( GetSystemMetrics(SM_CXMAXIMIZED) - 1020 ) / 2,
( GetSystemMetrics(SM_CYMAXIMIZED) - 600 ) / 2,
1020, 600, NULL, NULL, hInstance, 0 );
if(hwnd == NULL)
{
MessageBox( NULL, L"Window creation failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK );
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
// shutdownd GDI+
GdiplusShutdown(gdiplusToken);
return Msg.wParam;
}
Windows XP
和 MS Visual Studio C++ 2008 Express Edition
处理 pure Win32 API
。WM_ERASEBKGND
(返回的 (LRESULT)1
),并且我已经从我的窗口类中排除了样式 CS_VREDRAW
和 CS_HREDRAW
- 因此不应因此导致闪烁。WS_CLIPCHILDREN
样式,因为在静态控件所在的位置可以看到部分桌面图片。WM_SIZE
处理程序中,我有:SetWindowPos(...)
API 重新定位静态控件,并通过添加 SWP_NOCOPYBITS
标志减少闪烁。 InvalidateRect( hWnd, NULL, FALSE )
使整个窗口无效,因此该 API 在无效时不发送 WM_ERASEBKGND
(第三个参数是 FALSE
),但即使我尝试使用 TRUE
效果也是一样的。 WM_PAINT
处理程序实现了双缓冲,就像上述书籍/文章/教程中的示例一样(通过在内存 DC 中执行所有操作并在屏幕 DC 上执行 BitBlt(...)
以避免闪烁)。WM_SIZING
、 WM_WINDOWPOSCHANGING
或 WM_MOVING
消息。GDI leaks
。WS_EX_COMPOSITED
样式,性能并没有提高。WM_PAINT
处理程序留空并使用onPaint
API获取的设备上下文调用WM_ERASEBKGND
中的GetDC(..)
函数后,闪烁消失了,但在调整大小的过程中,窗口的重绘是“尖刺”的,并且主窗口边缘的问题没有解决了。最佳答案
我在 Windows 7 上编译并运行了代码。使用标准主题(使用 DWM )在调整大小时看起来很好。
我切换到 Windows 经典主题(禁用 DWM),当窗口调整大小时,按钮边缘有大量撕裂。我怀疑这是你看到的问题。
当绘画与屏幕的物理更新不同步时,就会发生撕裂。这导致部分屏幕显示旧图像,部分屏幕显示新图像。这种效果在水平移动的垂直线上尤为明显。
您还在使用 Windows XP 吗?
据我所知,防止在 XP 上撕裂的唯一方法是使用 DirectX 进行绘画并与 VSYNC 显式同步。尽管您可能能够使用现有的绘画代码并使用 DirectX 绘制最终位图。或者可能有其他一些同步机制。我不知道。
但是,由于该问题会在更高版本的 Windows 上自行修复,因此我不会做任何事情。
关于c++ - 双缓冲故障(2013 年 12 月 17 日更新),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20641566/
有人可以解释一下为什么这个脚本不起作用吗? function destroy(ID) { if (confirm("Deleting is a very bad thing! Sure?")
我正在尝试使 WCF Silverlight 故障按此方式工作: MSDN aricle 将 SL 故障添加到我的 Web.config 文件后,我收到以下警告: The element 'behav
这是我要删除的 Haskell 函数 2::Int和 5::Int从列表中: remPrimesFactors25 :: [Int] -> [Int] remPrimesFactors25 [] =
当我想用 ffmpeg 连接和录制两个 mp4 视频时,我遇到了这个问题。我得到的输出是: [concat @ 0x2566e80] DTS 4079 #0:0 (h264 (native) ->
我想在delphi中编写一个程序来模拟以特定速度移动的鼠标指针(类似于AutoIT MouseMove函数)。要么是我的代码错误,要么是 SetCursorPos 在被调用太多次后出现故障。这是我的功
我将“wa、or 和 id”(来自这些州的访问者)设置为重定向到 website1.com - 当我访问该网站时,它会将我重定向到 website1.com(因此它知道我在 WA) 。但如果我将 wa
我们目前正在争论通过 WCF channel 抛出错误与传递指示状态或服务响应的消息是否更好。 故障带有 WCF 的内置支持,您可以使用内置的错误处理程序并做出相应的 react 。然而,这会带来开销
不确定我在这里做错了什么,如果有任何帮助,我们将不胜感激。 尝试创建一个名为“control”的新变量,并在行变量等于这些数字时将其编码为 1,否则编码为 0。 data$control= ifels
我想在应用洞察中记录成功调用的百分比。我看到这篇文章https://learn.microsoft.com/en-us/azure/azure-monitor/app/sampling我认为固定速率采
我正在尝试使用 SVD 和特征分解来使用动态模式分解进行一些数据分析。我遇到了一个简单的问题,即从 Matlab 和 Python 获得不同的结果。我很困惑,不知道为什么 Python 给我错误的结果
This question already has an answer here: mysqli_fetch_assoc() expects parameter / Call to a member
我刚刚开始我的一个实验室,在那里我计算类(class)的 GPA,其信息存储在结构的链接列表中。截至目前,我正在尝试打印所有类(class)信息,以确保它们已正确初始化并添加到链接列表中。 我遇到了一
我正在尝试学习如何使用 visual studio 为 C++ 制作 GUI。但是我在使用 GetWindowText() 函数时遇到了一些问题。它不会将 LPTSTR 标题更改为文本框中的文本,并且
我有一个奇怪的问题。它似乎只出现在测试者的 iPhone 5s 上。它可以在运行最新 iOS (8.3) 的 iPhone 5、6 和 6 plus 上正常运行。 这是代码 -(NSString *)
我正在尝试更新 Core Data 中的一些记录。我正在采取以下步骤来完成它 带谓词的获取函数从核心数据中检索记录 将结果集存储在对象数组中 遍历数组并更新每条记录 调用保存上下文 我遇到了两个问题
我通过 Storyboard设计了 tableView,在一个单元格中我有一个按钮和一个标签。按钮在 Storyboard上有标签 1 和标签在 Storyboard上有标签 2。在 cellForR
我实现了这个方法,当在文本字段中输入了未经授权的字符或已使用的用户名时,向用户发送多个警报 View : func textFieldShouldEndEditing(textField: UITex
伙计们,我在运行程序时遇到了这个非常奇怪的错误。这是重要的代码: 变量(编辑): const short int maxX = 100; const short int maxZ = 100; con
我有这个修改过的 Matrix Javascript 代码,我想摆脱第一次运行的所有与自身重叠的字符串。有人知道我该如何管理吗?另外,我想在我的网页上多次使用此代码,我需要声明新变量,不是吗?但是当我
有谁知道是否有网站(甚至非 Microsoft)有关于 COMExceptions/HRESULTS 的详细信息。 当我尝试在使用 Copy() 函数后保存我的 Excel 工作簿时,我收到此错误:
我是一名优秀的程序员,十分优秀!