2011-11-10 94 views
4

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

现在我不是要求你们为我拼出来,只是开始。我将为此使用C++/ASM/Win32 API。我相信你们之中很多人都已经做过自定义的编辑控制,所以可能你甚至可以分享你的经验。

感谢,

Devjeet

+0

[Visual Studio的样品(http://archive.msdn.microsoft.com/vcsamplesmfc)有一个写字板和超垫样品 –

+0

谢谢,但实际上并非即时通讯寻找MFC教程。 – devjeetroy

+4

一旦您考虑到非英语语言,恰当的自定义编辑控制决非易事。我建议你重新考虑。 –

回答

0

你会希望寻找到所有者绘制控件。 MSDN有example of doing this with a list box。您可以将其调整为编辑控件。

+0

Pure Win32拥有者绘制控件具有非常大量的代码。如果你只是告诉我们你想用编辑框做什么可能会更好,也许有人会知道现有的解决方案,将为你工作。 –

+0

感谢您的response.ok,所以我想用它做一些基本的语法突出显示。没有花哨的东西。只需基本的语法高亮。我正在寻找有用的东西来开发,这看起来不错。之前我还没有开发过这样的规模,我期待这是一个非常有趣的体验。 – devjeetroy

+3

编辑控件没有“所有者绘制”样式。 http://msdn.microsoft.com/en-us/library/windows/desktop/bb775464%28v=vs.85%29.aspx因此,你不能*适应你的建议。 – Kissaki

4

我花了一天的时间写自己的自定义编辑控件 - 它运行良好,所以我会在这里分享我的经验,也许对于这个代码会有帮助的人...因为自定义绘制常见的编辑控件是不可能的(see here) ,您必须编写自己的编辑控件。一般步骤如下:

// 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); 

如何显示键盘输入描述here。我的窗口过程如下所示

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); 
} 

删除当前选中的文本(从选择光标)。

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 *)

绘制窗口。语法高亮和其他格式的功能放在这里......

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); 
    } 
}