主要问题是我想让滚动条点到静态文本区时不闪烁,所以用Enablewindow把两个滚动条先设置为FALSE后设置为TRUE,结果这么一跑后续想读取滚轮信息让图片缩放的功能失效了,但是加断点或者先点一下按钮这种控件又能跑了,这是什么原因,或者能让滚动条不闪烁的方法是什么。
HWND staPaint;
HWND btnInput;
HWND btnCount;
HWND staBegin;
HWND staEnd;
HWND scrVertical;
HWND scrHorizontal;
HBITMAP bmpImage;
int horizontalMax;
int verticalMax;
int horizontalNow = 0;;
int verticalNow = 0;;
double imageProportion = 1.0;
// 初始化窗口先注册,后创建
// 注册用WNDCLASSEx,RegisterClassEx,注册时要回调函数
// 创建用CreateWindowEx
enum class ResponseComponent
{
none = 0,
verticalscrollbar = 1,
horizontalscrollbar = 2,
paintregion = 3
};
ResponseComponent responsecomponent = ResponseComponent::none;
class Vec2
{
public:
double x, y;
Vec2() :x(0), y(0) {}
Vec2(double xx, double yy) :x(xx), y(yy) {};
Vec2 operator+(Vec2 num)
{
return Vec2(x + num.x, y + num.y);
}
Vec2 operator-(Vec2 num)
{
return Vec2(x - num.x, y - num.y);
}
Vec2 operator/(double num)
{
return Vec2(x / num, y / num);
}
Vec2 operator*(double num)
{
return Vec2(x * num, y * num);
}
};
class Rect
{
public:
Rect() :size(), position() {}
Rect(Vec2 position, Vec2 size) :size(size), position(position) {}
Vec2 size;
Vec2 position;
bool isInRect(Vec2 point)
{
Vec2 left_top = position - size / 2.0;
Vec2 right_buttom = position + size / 2.0;
if (point.x >= left_top.x && point.y >= left_top.y &&
point.x <= right_buttom.x && point.y <= right_buttom.y)return true;
return false;
}
Vec2 GetLeftTop()
{
return position - size / 2.0;
}
Vec2 GetRightDown()
{
return position + size / 2.0;
}
};
LRESULT __stdcall CallBackFunc_Main(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
bool RegisterWindow(HINSTANCE hinstance, const TCHAR* classname, COLORREF background,
LRESULT(*callbackfunc)(HWND, UINT, WPARAM, LPARAM))
{
// 一共12个值需要初始化
WNDCLASSEX wndcl;
wndcl.cbSize = sizeof(WNDCLASSEX);
wndcl.lpfnWndProc = callbackfunc;
wndcl.hInstance = hinstance;
wndcl.hCursor = LoadCursor(NULL, IDC_ARROW);
wndcl.lpszClassName = classname;
wndcl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndcl.cbClsExtra = 0;
wndcl.cbWndExtra = 0;
wndcl.hbrBackground = CreateSolidBrush(RGB(240, 240, 240));//CreateSolidBrush(background);
wndcl.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // 更改程序图标
wndcl.lpszMenuName = NULL;
wndcl.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
if (RegisterClassEx(&wndcl))return true;
return false;
}
HWND InitWindow(HINSTANCE hinstance, const TCHAR* classname, COLORREF background,
LRESULT(callbackfunc)(HWND, UINT, WPARAM, LPARAM), const TCHAR caption,
DWORD style, Rect place, HWND parent)
{
if (!RegisterWindow(hinstance, classname, background,callbackfunc))
{
MessageBox(NULL, TEXT("注册失败"), TEXT("错误"), MB_OK | MB_ICONERROR);
return NULL;
}
int left = place.position.x - place.size.x / 2.0;
int top = place.position.y - place.size.y / 2.0;
return CreateWindowEx(0, classname, caption, style,
left, top, place.size.x + 8, place.size.y + 30, parent, NULL, hinstance, NULL);
}
int __stdcall wWinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPWSTR cmdinstructor, int cmdnum)
{
MSG message;
HWND hwnd = InitWindow(hinstance, TEXT("WindowCourse"), RGB(240, 240, 240), CallBackFunc_Main, TEXT("窗口"),
WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME,
Rect(Vec2(500, 300), Vec2(640, 480)), HWND_DESKTOP);
if (!hwnd)return 1;
ShowWindow(hwnd, cmdnum);
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}
return message.wParam;
}
int main()
{
wWinMain(0, 0, 0, SW_SHOW);
return 0;
}
LRESULT __stdcall CallBackFunc_Main(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc, memDc;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
{
RECT rect;
GetWindowRect(hwnd, &rect);
Vec2 windowsize = Vec2(rect.right, rect.bottom) - Vec2(rect.left, rect.top) - Vec2(8, 30);
double paintsizeproportion_x = 0.9;
double paintsizeproportion_y = 0.8;
Rect paintregion(Vec2(windowsize.x * 0.7 * 0.5, windowsize.y * 0.5),
Vec2(windowsize.x * 0.7 * paintsizeproportion_x, windowsize.y * paintsizeproportion_y));
staPaint = CreateWindow(TEXT("STATIC"), TEXT(""),
WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_BORDER | SS_BITMAP,
paintregion.GetLeftTop().x, paintregion.GetLeftTop().y, paintregion.size.x, paintregion.size.y,
hwnd, (HMENU)IDS_PAINTREGION, 0, 0);
Rect verticalregion(Vec2(windowsize.x * 0.7 * (0.5 + 0.5 * paintsizeproportion_x)+10, windowsize.y * 0.5),
Vec2(20, windowsize.y * paintsizeproportion_y));
scrVertical = CreateWindow(TEXT("SCROLLBAR"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP | SBS_VERT,
verticalregion.GetLeftTop().x, verticalregion.GetLeftTop().y,
verticalregion.size.x, verticalregion.size.y, hwnd, 0, 0, 0);
Rect horizontalregion(Vec2(windowsize.x * 0.7 * 0.5, windowsize.y * (0.5 + 0.5 * paintsizeproportion_y)+10),
Vec2(windowsize.x * 0.7 * paintsizeproportion_x, 20));
scrHorizontal = CreateWindow(TEXT("SCROLLBAR"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_TABSTOP | SBS_HORZ,
horizontalregion.GetLeftTop().x, horizontalregion.GetLeftTop().y,
horizontalregion.size.x, horizontalregion.size.y, hwnd, 0, 0, 0);
verticalMax = 1170 - paintregion.size.y;
horizontalMax = 1824 - paintregion.size.x;
SCROLLINFO info;
info.cbSize = sizeof(SCROLLINFO);
GetScrollInfo(scrVertical, SB_CTL, &info);
info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
info.nMin = 0;
info.nMax = verticalMax + paintregion.size.y;
info.nPage = paintregion.size.y;
info.nPos = 0;
SetScrollInfo(scrVertical, SB_CTL, &info, FALSE);
GetScrollInfo(scrHorizontal, SB_CTL, &info);
info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
info.nMin = 0;
info.nMax = horizontalMax + paintregion.size.x;
info.nPage = paintregion.size.x;
info.nPos = 0;
SetScrollInfo(scrHorizontal, SB_CTL, &info, FALSE);
double buttonsizeproportion_x = 0.7;
double buttonsizeproportion_y = 0.5;
Rect inputregion(Vec2(windowsize.x * (0.7 + 0.3 * 0.5), windowsize.y * 0.25 * 0.5),
Vec2(windowsize.x * 0.3 * buttonsizeproportion_x, windowsize.y * 0.25 * buttonsizeproportion_y));
btnInput = CreateWindow(TEXT("BUTTON"), TEXT("输入地点"), WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_BORDER,
inputregion.GetLeftTop().x, inputregion.GetLeftTop().y, inputregion.size.x, inputregion.size.y,
hwnd, (HMENU)IDB_INPUT, 0, 0);
Rect countregion(Vec2(windowsize.x * (0.7 + 0.3 * 0.5), windowsize.y * (0.25 + 0.25 * 0.5)),
Vec2(windowsize.x * 0.3 * buttonsizeproportion_x, windowsize.y * 0.25 * buttonsizeproportion_y));
btnCount = CreateWindow(TEXT("BUTTON"), TEXT("计算路径"), WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_BORDER,
countregion.GetLeftTop().x, countregion.GetLeftTop().y, countregion.size.x, countregion.size.y,
hwnd, (HMENU)IDB_INPUT, 0, 0);
double staticsizeproportion_x = 0.7;
double staticsizeproportion_y = 0.5;
Rect beginregion(Vec2(windowsize.x * (0.7 + 0.3 * 0.5), windowsize.y * (0.25 * 2 + 0.25 * 0.5)),
Vec2(windowsize.x * 0.3 * staticsizeproportion_x, windowsize.y * 0.25 * staticsizeproportion_y));
staBegin = CreateWindow(TEXT("STATIC"), TEXT("起点:"), WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | SS_CENTER,
beginregion.GetLeftTop().x, beginregion.GetLeftTop().y, beginregion.size.x, beginregion.size.y,
hwnd, (HMENU)IDS_BEGINPLACE, 0, 0);
Rect endregion(Vec2(windowsize.x * (0.7 + 0.3 * 0.5), windowsize.y * (0.25 * 3 + 0.25 * 0.5)),
Vec2(windowsize.x * 0.3 * staticsizeproportion_x, windowsize.y * 0.25 * staticsizeproportion_y));
staEnd = CreateWindow(TEXT("STATIC"), TEXT("终点:"), WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | SS_CENTER,
endregion.GetLeftTop().x, endregion.GetLeftTop().y, endregion.size.x, endregion.size.y,
hwnd, (HMENU)IDS_ENDPLACE, 0, 0);
}
break;
case WM_COMMAND:
switch (HIWORD(wParam))
{
case BN_CLICKED:
switch (LOWORD(wParam))
{
case IDB_INPUT:
responsecomponent = ResponseComponent::none;
break;
case IDB_COUNT:
responsecomponent = ResponseComponent::none;
break;
}
break;
}
break;
case WM_LBUTTONUP:
{
short mouse_y = HIWORD(lParam); // y
short mouse_x = LOWORD(lParam); // x
RECT paintrect, winrect, rect;
GetWindowRect(staPaint, &paintrect);
GetWindowRect(hwnd, &winrect);
rect.left = paintrect.left - winrect.left;
rect.right = paintrect.right - winrect.left;
rect.top = paintrect.top - winrect.top;
rect.bottom = paintrect.bottom - winrect.top;
if (mouse_x > rect.left && mouse_x < rect.right && mouse_y > rect.top && mouse_y < rect.bottom)
{
EnableWindow(scrVertical, FALSE);
EnableWindow(scrHorizontal, FALSE);
EnableWindow(scrHorizontal, TRUE);
EnableWindow(scrVertical, TRUE);
responsecomponent = ResponseComponent::paintregion;
}
else
{
EnableWindow(scrVertical, FALSE);
EnableWindow(scrHorizontal, FALSE);
responsecomponent = ResponseComponent::none;
EnableWindow(scrVertical, TRUE);
EnableWindow(scrHorizontal, TRUE);
}
}
break;
// case WM_LBUTTONUP:
//
// break;
case WM_ENABLE:
{
int num = 0;
}
break;
case WM_MOUSEWHEEL:
{
// 高往下是负,往上是正
short num_hi = HIWORD(wParam);
switch (responsecomponent)
{
case ResponseComponent::none:
break;
case ResponseComponent::verticalscrollbar:
if (num_hi < 0)verticalNow = min(verticalNow + 20, verticalMax);
else if (num_hi > 0)verticalNow = max(verticalNow - 20, 0);
SetScrollPos(scrVertical, SB_CTL, verticalNow, TRUE);
InvalidateRect(hwnd, NULL, FALSE);
break;
case ResponseComponent::horizontalscrollbar:
if (num_hi < 0)horizontalNow = min(horizontalNow + 20, horizontalMax);
else if (num_hi > 0)horizontalNow = max(horizontalNow - 20, 0);
SetScrollPos(scrHorizontal, SB_CTL, horizontalNow, TRUE);
InvalidateRect(hwnd, NULL, FALSE);
break;
case ResponseComponent::paintregion:
{
SCROLLINFO scrollinfo;
scrollinfo.cbSize = sizeof(SCROLLINFO);
GetScrollInfo(scrVertical, SB_GRAD_TRI, &scrollinfo);
if (num_hi < 0)
imageProportion += 0.1;
else if (num_hi > 0)
imageProportion -= 0.1;
InvalidateRect(hwnd, NULL, FALSE);
}
break;
default:
break;
}
}
break;
case WM_PAINT:
{
RECT rect;
hdc = BeginPaint(staPaint, &ps);
memDc = CreateCompatibleDC(hdc);
bmpImage = (HBITMAP)LoadImage(NULL, TEXT("map.bmp"), IMAGE_BITMAP, 1824, 1170, LR_LOADFROMFILE);
SelectObject(memDc, bmpImage);
GetWindowRect(staPaint, &rect);
// BitBlt(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, memDc,
// horizontalNow, verticalNow, SRCCOPY);
StretchBlt(hdc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, memDc, horizontalNow, verticalNow,
imageProportion* (rect.right - rect.left), imageProportion* (rect.bottom - rect.top), SRCCOPY);
DeleteObject(bmpImage);
DeleteDC(memDc);
EndPaint(staPaint, &ps);
}
break;
case WM_VSCROLL:
switch (LOWORD(wParam))
{
case SB_PAGEDOWN:
verticalNow += 20;
case SB_LINEDOWN:
verticalNow = min(verticalMax, verticalNow + 1);
break;
case SB_PAGEUP:
verticalNow -= 20;
case SB_LINEUP:
verticalNow = max(0, verticalNow - 1);
break;
case SB_TOP:
verticalNow = 0;
break;
case SB_BOTTOM:
verticalNow = verticalMax;
break;
case SB_THUMBPOSITION:
verticalNow = HIWORD(wParam);
// EnableWindow(scrVertical, FALSE);
// EnableWindow(scrVertical, TRUE);
responsecomponent = ResponseComponent::verticalscrollbar;
break;
case SB_THUMBTRACK:
verticalNow = HIWORD(wParam);
break;
default:
break;
}
SetScrollPos(scrVertical, SB_CTL, verticalNow, TRUE);
InvalidateRect(hwnd, NULL, FALSE);
break;
case WM_HSCROLL:
switch (LOWORD(wParam))
{
case SB_PAGERIGHT:// 用户单击滚动条右方的滚动条轴
horizontalNow += 20;
break;
case SB_PAGELEFT:
horizontalNow -= 20;
break;
case SB_LINELEFT:// 用户单击左滚动箭头
horizontalNow = min(horizontalNow + 1, horizontalMax);
break;
case SB_LINERIGHT:
horizontalNow = max(horizontalNow - 1, 0);
break;
case SB_THUMBTRACK:// 拖动滑块
horizontalNow = HIWORD(wParam);
break;
case SB_THUMBPOSITION:// 拖动后松开
horizontalNow = HIWORD(wParam);
// EnableWindow(scrHorizontal, FALSE);
// EnableWindow(scrHorizontal, TRUE);
responsecomponent = ResponseComponent::horizontalscrollbar;
break;
}
SetScrollPos(scrHorizontal, SB_CTL, horizontalNow, TRUE);
InvalidateRect(hwnd, NULL, FALSE);
break;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
具体来说就是这个问题怎么解决
在代码中,在处理WM_LBUTTONUP(鼠标左键点击)事件时,禁用并立即启用了滚动条。这可能导致滚动条暂时无法接收消息,从而导致读取滚轮信息的功能失效。
如果主要目标是防止滚动条在点击静态文本区时闪烁,以下是一些可能的解决方案:
降低重绘的频率:当你需要改变窗口样式或者其它属性,并且不希望用户看到窗口改变的过程,可以采用下面的方式:
SetWindowRedraw(scrVertical, FALSE);
// 修改窗口属性的代码
SetWindowRedraw(scrVertical, TRUE);
这会在修改窗口属性的过程中关闭窗口的绘制,直到属性修改完成后再开启。这样就避免了窗口在修改期间的重绘,也就避免了滚动条的闪烁问题。
更改绘图策略:如果滚动条的闪烁是由于重绘引起的,可以尝试更改绘图策略。例如,使用双缓冲技术来减少或消除闪烁。
使用自定义滚动条:如果上述方法仍不能解决问题,那么可能需要考虑使用自定义滚动条。这将允许你有更多的控制,您可以自定义滚动条的外观和行为。