在获得焦点时更改编辑控件的背景

问题描述 投票:0回答:2

我想更改该控件的 EN_SETFOCUS 中的编辑控件(即常规编辑窗口类)的背景颜色。我知道我应该处理 WM_CTLCOLOR,在我得到的 DC 上执行 SetBkColor(),并返回带有背景颜色的画笔的句柄。但是,当我从 EN_SETFOCUS 执行此操作时,我的控件不会正确失效或重绘。基本上我的文本周围有一个颜色错误的 1 像素边框;因此黑色边框内的矩形已经位于控件本身周围。如果我将鼠标光标移到控件上,错误边框的某些部分会正确重绘,有时整个工件会在一小段时间后消失,就好像某个计时器导致完全重绘一样。

我尝试过在不同的地方使控件无效,例如DC上的RedrawWindow、SelectRgn(NULL),使用对话框的wS_CLIPCHILDREN和-SIBLINGS,使控件所在的矩形上的对话框无效,但这些都不起作用。我还在 2001 年的一篇帖子中发现了对类似问题的模糊引用(!),但没有解决方案。有人遇到过这种情况吗?关于我可以尝试的其他事情有什么想法吗?

FWIW,这是在 WinXP 上使用 VS9,并使用 MFC,但我也“手动”发送消息,这并没有改变任何东西,我不认为 MFC 在这种情况下是罪魁祸首。当然我可能是错的:)

编辑:

下面屏幕截图的对话框代码(最小示例)位于:http://pastebin.com/zepdhdp5。这是一个由向导生成的小型应用程序 - 没什么特别的,完整的源代码可以从 https://www.dropbox.com/s/d8nxaryoo0vclue/edit_control_redrawing_sample.zip .

下载

控件获得焦点后如下所示:

enter image description here

当它失去焦点时就像这样:

enter image description here

如您所见,文本区域周围似乎有一个不会失效的边框。

我尝试用纯win32重现这个问题,但是当我不使用commonctrl6时,它不会出现这个问题。不过,我无法让 commonctrl6 在 win32 中工作,所以我现在怀疑它与此有关。

winapi mfc
2个回答
5
投票

你知道什么 - 经过一天间歇性尝试各种事情并在谷歌搜索中尝试不同角度后,我发现了神奇的关键字:非客户区失效。这让我找到了 http://forums.codeguru.com/showthread.php?307470-Invalidate-NC-area ,其中包含解决方案:

SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_DRAWFRAME);

(在 SetFocus/KillFocus 处理程序中) 我的理论是,commonctrl6 视觉样式管理器将编辑控件周围的边框视为非客户区域,并错误地计算了当控件获得焦点时使该区域无效一个像素。 SWP_DRAWFRAME 似乎是唯一强制完全更新控件的东西,带有 RDW_FRAME 的 RedrawWindow() 并没有削减它。

啊好吧,希望我在这里的问题至少可以让某人免于像我一样浪费时间......


0
投票

为其他可能有同样问题的人写这个答案:)

//static variable, which is once create on the begin of function
static red_brush = CreateSolidBrush(RGB(255, 0, 0));

(...)

case WM_CTLCOLOREDIT:

        //operating window
        if((HWND)lParam == example)
        {
            //static flag redraw - have to static
            static int flag_redraw;

            //set background color: red
            SetBkColor((HDC)wParam, RGB(255, 0, 0));

            //once redraw window
            if(flag_redraw == false)
            {
                InvalidateRect(address, NULL, true);

                //send WM_PAINT on the begin of queue of communicats
                UpdateWindow(address);

                //change value of flag_redraw
                flag_redraw = true;

                //after redraw window ShowCarret
                ShowCaret(address);
            }
            
            //when the window is redrawing, communicate WM_CTLCOLOREDIT is proccessed - in this case musn't to again redraw
            else
                //reset redraw flag
                flag_redraw = false;
                
        //return red_brush
        return (BOOL)red_brush;
        
    break;
    //case WM_CTLCOLOREDIT

也许解决方案并不优雅,但有效:)

© www.soinside.com 2019 - 2024. All rights reserved.