自定义编辑控件win32 [英] Custom edit control win32

查看:128
本文介绍了自定义编辑控件win32的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我终于设法使用richedit和iczelion的教程来突出显示语法。
现在我找到了,它肯定不够快。我正在考虑迈出这一步:自定义编辑控件。但是我不知道该怎么做。你们能告诉我怎么做吗?给我一些信息开始吗?也许甚至一些教程或建议一些书?

I finally managed to get my syntax highlighting done using richedit and iczelion's tutorials. Now that i find it, it certainly is not fast enough. I am thinking of taking this one step ahead: a custom edit control. But i do not know how to go about it. Could you guys tell me how to go about it? Give me some info to start on? Maybe even some tutorial or suggest some book?

现在,我不是要你们为我拼出来,只是要开始。我将为此使用C ++ / ASM / Win32 API。我敢肯定,你们中的许多人以前已经做过自定义编辑控件,所以也许您甚至可以分享自己的经验。

Now I'm not asking for you guys to spell it out for me, just something to start on. I will be using C++/ASM/Win32 API for this. I'm sure many of you have already made custom edit controls befores, so may be you could even share your experience.

谢谢,

Devjeet

推荐答案

我花了一天的时间编写自己的自定义编辑控件-效果很好,所以我想在这里分享我的经验,也许对某些人来说,这段代码可能会有所帮助...因为自定义绘制不可能实现通用的编辑控件(请参见此处),则必须编写自己的编辑控件。一般步骤为:

I spent one day on coding my own custom edit control - it's working well, so I would like to share my experience here, maybe for someone this code might be helpful... Because custom draw an common edit control is impossible (see here), you must write your own edit control. The general steps are:

// global vars
int select; // current selection position
int cursor; // current cursor position
HWND parent; // parent window
wchar_t buf[MAXINPUTBUF]; // edit buffer
WNDPROC oldproc; // old window procedure

// create custom control window
hWnd = CreateWindowW(L"static", NULL, WS_CHILD | WS_TABSTOP | SS_LEFT | SS_NOTIFY, 0, 0, 0, 0, parent, NULL, (HINSTANCE)GetWindowLongPtr(parent, GWL_HINSTANCE), NULL);

// todo: use SetProp() to store all global vars
oldproc = (WNDPROC)SetWindowLongPtrW(hWnd, GWL_WNDPROC, (LONG_PTR)InputWndProc);

SetWindowPos(hWnd, HWND_TOP, x, y, cx, cy, 0);

描述了如何显示键盘输入此处。我的窗口过程如下所示:

How to display keyboard input is described here. My window procedure looks as follows

LRESULT CALLBACK InputWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    switch (msg)
    {
    case WM_LBUTTONDOWN:
        //SetFocus(hWnd);
        PostMessageW(GetParent(hWnd), WM_NEXTDLGCTL, (WPARAM)hWnd, TRUE);
        break;

    case WM_KILLFOCUS: 
        HideCaret(hWnd);
        DestroyCaret();
        break; 

    case WM_SETFOCUS:
        {
            RECT r;
            GetClientRect(hWnd, &r);
            // Create a solid black caret. 
            CreateCaret(hWnd, (HBITMAP) NULL, 2, r.bottom-r.top);

            ShowCaret(hWnd);
            InputWndRedraw(hWnd);

        }

        return FALSE;

    case WM_GETDLGCODE:
        return DLGC_WANTALLKEYS | DLGC_WANTARROWS;

    case WM_KEYDOWN:
    {
        switch (wParam)
        {
        case 'V':
            if (0x8000 & GetKeyState(VK_CONTROL))
            {
                HANDLE h;
                wchar_t *cb;
                int len,slen;

                InputWndDelete(hWnd);

                OpenClipboard(NULL);
                h = GetClipboardData(CF_UNICODETEXT);

                cb = (wchar_t*)GlobalLock(h);

                if (cb)
                {
                    memcpy(buf+(cursor+len)*sizeof(wchar_t), buf+cursor*sizeof(wchar_t), (slen-cursor)*sizeof(wchar_t));
                    memcpy(buf+cursor*sizeof(wchar_t), cb, len*sizeof(wchar_t));
                }

                GlobalUnlock(h);
                CloseClipboard();
                InputWndRedraw(hWnd);
            }
            break;

        case VK_RIGHT:

                if (cursor-1 >= MAXINPUTBUF || cursor >= (int)wcslen(buf))
                    break;

                cursor++;

                if (!(GetKeyState(VK_SHIFT) & 0x8000))
                    select = cursor;

                InputWndRedraw(hWnd);
                break;

            case VK_TAB:
                PostMessageW(GetParent(hWnd), WM_NEXTDLGCTL, GetKeyState(VK_SHIFT) & 0x8000, FALSE);
                break;

            case VK_LEFT:
                if (cursor <= 0)
                    break;

                cursor--;

                if (!(GetKeyState(VK_SHIFT) & 0x8000))
                    select = cursor;

                InputWndRedraw(hWnd);
                break;

            case VK_HOME:
                cursor = 0;

                if (!(GetKeyState(VK_SHIFT) & 0x8000))
                    select = cursor;

                InputWndRedraw(hWnd);
                break;

            case VK_END:
                cursor = wcslen(buf);

                if (!(GetKeyState(VK_SHIFT) & 0x8000))
                    select = cursor;

                InputWndRedraw(hWnd);
                break;

            case VK_DELETE:
                if (cursor >= (int)wcslen(buf))
                {
                    InputWndDelete(hWnd);
                    InputWndRedraw(hWnd);
                    break;
                }

                if (select == cursor)
                    select ++;

                InputWndDelete(hWnd);
                InputWndRedraw(hWnd);
            break;

            case VK_BACK:

                if (cursor <= 0)
                {
                    InputWndDelete(hWnd);
                    InputWndRedraw(hWnd);
                    break;
                }


                if (select == cursor)
                    cursor --;


                InputWndDelete(hWnd);
                InputWndRedraw(hWnd);
            }

        }
        break;

    case WM_CHAR: 
        if (wParam < VK_SPACE)
        break;


        InputWndDelete(hWnd);

        if (wcslen(buf)+1 < MAXINPUTBUF)
        {
            wmemmove(buf+(cursor+1)*sizeof(wchar_t), buf+cursor*sizeof(wchar_t), wcslen(s->buf)-cursor);
            buf[cursor] = wParam;
            cursor++;
            select = cursor;
        }

        InputWndRedraw(hWnd);

        break;

    case WM_ERASEBKGND:
        // no flickering
        return TRUE;

    case WM_PAINT:
        {
            HDC dc;
            PAINTSTRUCT paint;

            dc = BeginPaint(hWnd, &paint);
            InputWndDraw(hWnd, dc);
            EndPaint(hWnd, &paint);

        }
        return TRUE;

    }

    return CallWindowProcW(oldproc, hWnd, msg, wParam, lParam);
}

删除当前选定的文本(从 select cursor )。

Delete current selected text (from select to cursor).

void InputWndDelete(HWND hWnd)
{
    int len;

    len = wcslen(buf);

    if (select > cursor)
    {
        memcpy(buf+cursor*sizeof(wchar_t), buf+select*sizeof(wchar_t), (len - select)*sizeof(wchar_t));
        ZeroMemory(buf+(len-select+cursor)*sizeof(wchar_t), (MAXINPUTBUF-len+select-cursor)*sizeof(wchar_t));
        select = cursor;
    }
    else if (select < cursor)
    {
        memcpy(buf+select*sizeof(wchar_t), buf+cursor*sizeof(wchar_t), (len - cursor)*sizeof(wchar_t));
        ZeroMemory(buf+(len-cursor+select)*sizeof(wchar_t), (MAXINPUTBUF-len+cursor-select)*sizeof(wchar_t));
        cursor = select;
    }
    else
    {
        select = cursor;
    }
}

在DC窗口上绘制窗口

void InputWndRedraw(HWND hWnd)
{
    HDC hdc;

    HideCaret(hWnd); 

    hdc = GetDC(hWnd); 
    InputWndDraw(hWnd, hdc);
    ReleaseDC(hWnd, hdc); 

    ShowCaret(hWnd); 

}

在设备上下文上绘制输入缓冲区(buf *)。语法高亮和其他格式设置功能在这里...

Draw input buffer (buf*) on device context. Syntax highlighting and other formatting features goes here...

void InputWndDraw(HWND hWnd, HDC hdc)
{
    RECT r,cr;

    GetClientRect(hWnd, &cr);

    // draw selected rectangle FillRect()...

    CopyRect(&r,&cr);
    DrawTextW(hdc, buf, -1, &r, DT_LEFT | DT_TOP);


    if (cursor)
        DrawTextW(hdc, buf, cursor, &r, DT_LEFT | DT_TOP | DT_CALCRECT);
    else
        r.right = cr.left;

    if (GetFocus() == hWnd)
    {
        if (r.right > cr.right)
            SetCaretPos(cr.right, cr.top); 
        else
            SetCaretPos(r.right, cr.top); 
    }
}

这篇关于自定义编辑控件win32的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆