"Windows Programming" series Tenth: Text caret

Source: Internet
Author: User
Tags textout



You know, when you create a project using Microsoft's programming environment, you choose whether it is console mode or Windows application. If you choose Console mode, a dark character mode window will appear at run time, with a caret waiting for the input to flash. The input cursor exists from the time of the DOS, but it gives a more powerful function in the Win32. Is the cmd window of Windows, where the input point is the insertion cursor:

Note that here the caret or insertion cursor is not another "cursor" in Windows, here is the position to indicate the insertion of characters, rather than for the mouse, handwriting, etc. can be positioned, moving the cursor (cursor), but the caret caret, this article also becomes the insertion cursor, note the insertion of the word, For convenience, the following is also referred to as the cursor or caret in this article, but note that this cursor is not the cursor.

Why is there an insertion cursor (caret)? Knowing the basic question, it was half done. We know that computers can enter various characters and controls through the keyboard, so there is a natural problem, where should the input characters be placed on the screen? This is why the cursor is created, and the cursor is actually a character insertion identifier. In short, we want to put the character into which position, we first set the caret there, the setting is actually to tell the computer input characters you show me where! From this we can also infer that the caret can only have one at a time.

    • Cursor-related API functions

To use the cursor, first create a cursor with the API function to create the cursor:

BOOL CreateCaret (HWND hwnd, HBITMAP hbitmap, int nwidth, int nheight);

The HWND parameter indicates which window the cursor belongs to.

The HBITMAP parameter is a handle to a bitmap that the computer uses as the cursor shape using the bitmap of the handle.

Since the cursor is for the person using the computer to insert characters, it has to have a shape for the user to see, so the cursor needs to have a small visible icon. Of course, for different situations and needs, Windows allows us to customize the shape of the cursor. Common bitmap creation or loading API functions such as CreateBitmap, CreateDIBitmap, LoadBitmap, and so on can be created or loaded with a bitmap, with the handle as the parameter.

Nwidth and nheight are the width and height of the bitmap respectively.

After the cursor is created, it is not automatically displayed, it is the default is hidden, you need to actively invoke the following display function:

BOOL ShowCaret (HWND hwnd);

Of course there are display cursors that can also hide the cursor:

BOOL HideCaret (HWND hwnd);

The parameters of the above two functions are simple and are to show the handle of the window.

To set the position of the caret, use the following API function:

BOOL setcaretpos (int X, int Y);

The parameters x, y are the coordinates relative to the window client area, respectively.

We can get the position of the current cursor with the following API function:

BOOL Getcaretpos (Lppoint lppoint);

The parameter lppoint returns the position where the current cursor is located.

We know that the cursor will blink, the flashing time interval can be set, we can use the following API to set and get the insertion cursor blink time:

BOOL setcaretblinktime (UINT umseconds); UINT Getcaretblinktime (VOID);

The parameter umseconds is the number of milliseconds between flashes.

The cursor needs to be destroyed when it is not used at last:

BOOL Destroycaret (VOID);


    • Cursor Handling related messages

The messages associated with the insertion cursor are mainly wm_setfocus, Wm_killfocus. The cursor is typically created and displayed in Wm_setfocus, while the cursor is destroyed in Wm_killfocus. Generally should be combined with WM_KEYDOWN and WM_CHAR messages to achieve text input.

    • Cursor Application Example

Here is a simple virtual terminal, many of our common terminal software is to achieve this, such as common securecrt, Tera term, Xshell, putty and so on. This example is to use the insertion cursor to implement character input, insert, the complete example code is as follows:

#include <windows.h>static TCHAR szwinname[] = TEXT ("virtualterminal"), #define Textmatrix (x, y) * (Ptextmatrix + ( Y) * nlinechars) + (x)) static Textmetric TM; Metric dimention of Virtual terminalstatic TCHAR *ptextmatrix; VT character Bufferstatic int ncharwidth, ncharheight; The width and height of characetersstatic int ncaretposx, ncaretposy; The current position of caretstatic int nvtwidth, nvtheight; The width and height of virtual terminal windowstatic int nlinechars, nrowchars; Character number in one line and rowstatic int ncaretoffsety; The offset of vertical heightstatic colorref textcolor; Text color for terminal window, which is fore colorstatic LRESULT CALLBACK Vtwndproc (HWND hwnd, UINT message, WPARAM WPar AM, LPARAM LPARAM);    HWND Createvirtualterminal (HWND hwndparent, int left, int top, int width, int height, int id) {HWND hwnd;    Wndclass Wndclass;    HInstance HInst = GetModuleHandle (NULL); Wndclass.style = Cs_hredraw |    Cs_vredraw;Wndclass.lpfnwndproc = Vtwndproc;    Wndclass.cbclsextra = 0;    Wndclass.cbwndextra = 0;    Wndclass.hinstance = HInst;    Wndclass.hicon = LoadIcon (NULL, idi_application);    Wndclass.hcursor = LoadCursor (NULL, Idc_arrow);    Wndclass.hbrbackground = (hbrush) getstockobject (Black_brush);    Wndclass.lpszmenuname = NULL;    Wndclass.lpszclassname = Szwinname; if (!    RegisterClass (&wndclass)) {return 0; } hWnd = CreateWindowEx (0, Szwinname, NULL, ws_child|    Ws_visible, left, top, width, height, hwndparent, (HMENU) ID, hInst, NULL); return hWnd;}    static void Drawchar (HDC hdc, int x, int y, TCHAR *str, int num) {rect rect;    SelectObject (HDC, Getstockobject (System_fixed_font));    SetTextColor (HDC, TextColor);    SetBkMode (HDC, TRANSPARENT);    Rect.left = x;    Rect.top = y;    rect.right = x + num * ncharwidth;    Rect.bottom = y + ncharheight;  FillRect (HDC, &rect, (Hbrush) Getstockobject (Black_brush));  TextOut (HDC, Ncaretposx * ncharwidth, Ncaretposy * ncharheight, &textmatrix (Ncaretposx, ncaretposy), NLi NECHARS-NCARETPOSX);}    Static LRESULT CALLBACK Vtwndproc (HWND hwnd, UINT message, WPARAM WPARAM, LPARAM LPARAM) {int x, y;    HDC hdc;        Switch (message) {Case WM_CREATE:HDC = GetDC (hWnd);        SelectObject (HDC, Getstockobject (System_fixed_font));        GetTextMetrics (HDC, &AMP;TM);        ReleaseDC (HWnd, HDC);        Ncharwidth = Tm.tmavecharwidth;        Ncharheight = Tm.tmheight;        TextColor = RGB (255, 255, 255);        Ncaretoffsety = 12;    return 0;        Case wm_size:nvtwidth = LoWord (LParam);        Nlinechars = max (1, nvtwidth/ncharwidth);        Nvtheight = HiWord (LParam);                Nrowchars = max (1, nvtheight/ncharheight);        if (Ptextmatrix! = NULL) {free (Ptextmatrix);        } Ptextmatrix = (TCHAR *) malloc (Nlinechars * nrowchars); if (Ptextmatrix) {for (y=0; y<nrowchars; y++) {for (x=0; x<nlinechars; x + +) {Textmatrix (x, y) = TE                XT (");        }}} setcaretpos (0, ncaretoffsety);    return 0;        Case Wm_lbuttondown:setfocus (HWND);    Break            Case Wm_keydown:switch (wParam) {case vk_home://HOME ncaretposx = 0;         Break            Case Vk_end://END ncaretposx = nLineChars-1;         Break             Case Vk_prior://Page up ncaretposy = 0;         Break             Case Vk_next://Page down ncaretposy = nRowChars-1;         Break             Case Vk_left://left arrow NCARETPOSX = max (nCaretPosX-1, 0);         Break             Case Vk_right://Right arrow Ncaretposx = min (ncaretposx + 1, nLineChars-1);         Break Case VK_UP://UpArrow Ncaretposy = max (nCaretPosY-1, 0);         Break             Case Vk_down://down arrow ncaretposy = min (ncaretposy + 1, nRowChars-1);         Break Case Vk_delete://DELETE//Move all the characters that followed the//deleted character (o              n the same line) one//space back in the matrix.             for (x = ncaretposx; x < nlinechars; x + +) Textmatrix (×, ncaretposy) = Textmatrix (x + 1, ncaretposy);             Replace the last character in the//line with a space.             Textmatrix (nLineChars-1, ncaretposy) = ";             The application would draw outside the//WM_PAINT message processing, so hide the caret.             HideCaret (HWND);             Redraw the line, adjusted for the//deleted character.             HDC = GetDC (hWnd); Drawchar (HDC, NCARETPOSX * ncharwidth, Ncaretposy * ncharheight, &textmatrix (Ncaretposx, ncaretposy), Nlinechars-ncaretposx/ncharwidth            );             ReleaseDC (HWnd, HDC);             Display the caret.         ShowCaret (HWND);         Break         }//Adjust the caret position based on the//Virtual-key processing.         Setcaretpos (NCARETPOSX * ncharwidth, Ncaretposy * ncharheight + ncaretoffsety);    return 0;        Case Wm_showwindow:setfocus (HWND);    Break        Case Wm_setfocus:createcaret (HWnd, NULL, Ncharwidth, 2);        Setcaretpos (NCARETPOSX * ncharwidth, Ncaretposy * ncharheight + ncaretoffsety);        ShowCaret (HWND);    Break        Case Wm_killfocus:case Wm_destroy:hidecaret (hWnd);        Destroycaret ();    Break            Case Wm_char:switch (wParam) {case 0x08://process a backspace.                if (Ncaretposx > 0) {ncaretposx--; SendMessage (HWnd, Wm_keydoWN, Vk_delete, 1L);        } break;            Case 0X09://process a tab.            do {SendMessage (hWnd, WM_CHAR, TEXT ("), 2L);            } while (ncaretposx% 4 = 0);        Break            Case 0x0D://process a carriage return.            NCARETPOSX = 0;            if (++ncaretposy = = nrowchars) {ncaretposy = 0;        } break;            Case 0x1b:case 0x0A://process a linefeed.            MessageBeep ((UINT)-1);        Break            Default:textmatrix (NCARETPOSX, ncaretposy) = (TCHAR) WParam;            HideCaret (HWND);            HDC = GetDC (hWnd);            Drawchar (HDC, Ncaretposx * ncharwidth, Ncaretposy * ncharheight, &textmatrix (Ncaretposx, Ncaretposy), 1);            ReleaseDC (HWnd, HDC);            ShowCaret (HWND);                if (++ncaretposx = = nlinechars) {ncaretposx = 0; if (++ncaretposy = = Nrowchars) {                    Ncaretposy = 0;        }} break;        } setcaretpos (NCARETPOSX * ncharwidth, Ncaretposy * ncharheight + ncaretoffsety);    return 0;            Case WM_PAINT: {paintstruct ps;            HDC = BeginPaint (hWnd, &ps);            SelectObject (HDC, Getstockobject (System_fixed_font));            SetBkMode (HDC, TRANSPARENT);            SetTextColor (HDC, TextColor); for (y=0; y<nlinechars; y++) {TextOut (HDC, 0, y * ncharheight, &textmatrix (0, y), Nlinec            HARs);        } endpaint (HWnd, &ps);    } return 0;    Default:break; } return DefWindowProc (hWnd, message, WParam, LParam);}

Below is the main program file, which invokes the Createvirtualterminal function above to create a window.

#include <windows.h> #define Idc_vtid 9876static TCHAR szappname[] = TEXT ("Caret demo"); static LRESULT CALLBACK WNDP ROC (hwnd, UINT, WPARAM, LPARAM), extern hwnd Createvirtualterminal (HWND hwndparent, int left, int top, int width, int Heig HT, int id); int WINAPI WinMain (hinstance hinstance, hinstance hprevinstance, PSTR szcmdline, int icmdshow) {HWND h     Wnd;     MSG msg;     Wndclass Wndclass; Wndclass.style = Cs_hredraw |     Cs_vredraw;     Wndclass.lpfnwndproc = WndProc;     Wndclass.cbclsextra = 0;     Wndclass.cbwndextra = 0;     Wndclass.hinstance = hinstance;     Wndclass.hicon = LoadIcon (NULL, idi_application);     Wndclass.hcursor = LoadCursor (NULL, Idc_arrow);     Wndclass.hbrbackground = (hbrush) getstockobject (White_brush);     Wndclass.lpszmenuname = NULL;     Wndclass.lpszclassname = Szappname; if (! RegisterClass (&wndclass)) {MessageBox (NULL, TEXT ("This program requires Windows nt!"), Szappname, mb_iCONERROR);     return 0;            } hWnd = CreateWindow (szappname,//window class name Szappname,        Window caption Ws_overlappedwindow,//window style cw_usedefault,                          Initial x position Cw_usedefault,//initial y position                          ×,//initial x size,//initial y size                          NULL,//parent window handle NULL,//Window menu handle                HINSTANCE,//program instance handle NULL);     Creation Parameters ShowWindow (hWnd, icmdshow);          UpdateWindow (HWND);          while (GetMessage (&msg, NULL, 0, 0)) {translatemessage (&msg);     DispatchMessage (&AMP;MSG); } return Msg.wparam;}Static LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM WPARAM, LPARAM LPARAM) {HDC hdc;    Paintstruct PS;        Switch (message) {case wm_create:createvirtualterminal (hWnd, ten, ten, N, Idc_vtid);    return 0;        Case WM_PAINT:HDC = BeginPaint (hWnd, &ps);        ;        EndPaint (HWnd, &ps);    return 0;        Case Wm_destroy:postquitmessage (0);    return 0; } return DefWindowProc (hWnd, message, WParam, LParam);}

After the sample program runs, enter some text in the window (mimicking the cmd window above ^_^), the effect is as follows:

This example realizes a simple terminal simulation applet, for the convenience of readers reuse, I will be the terminal simulation of the small window as a complete source file, and the window background is set to black, the foreground color is set to white, looks more like CMD, Linux and other command-line windows.

More experience Exchange can join the Windows programming discussion QQ Group :454398517.


focus on the public platform: Programmer Interaction Alliance (coder_online), you can first get original technical articles, and (Java/c/c++/android/windows/linux) technology Daniel Friends, online communication programming experience, get programming basics, solve programming problems. Programmer Interactive Alliance , developer's own home.

Reprint please indicate the source http://www.coderonline.net/?p=1905, thank you for your cooperation!



Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

"Windows Programming" series Tenth: Text caret

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.