2011-11-10 91 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); 
    } 
}