How to change windows blink cursor shape from c++?

2019-07-01 17:38发布

问题:

How to change windows blink cursor shape from vertical which is by default ( | ) to horizontal like that used in dos ( _ ).

Is there some good function that take care about that?

OS: win7

回答1:

This is actually called a caret, rather than a cursor. That's probably where the confusion comes from, and why searching for a solution didn't yield very much of use. NullPonyPointer's comment reflects this common confusion as well. The SetCursor function is indeed what you would want to change the mouse cursor, but it won't work to change the caret.

Fortunately, there is a whole group of Windows functions that work with carets: CreateCaret, ShowCaret, HideCaret, SetCaretPos, and DestroyCaret. There are some others for manipulating blink time, but I recommend sticking to the user's current settings (which will be the default).

First, a bit of background. I strongly recommend reading the two introductory MSDN articles about carets and on using carets. But here's a quick summary: The caret is owned by a window; in particular, the window that currently has the focus. This window will likely be something like a text box control. When the window receives the focus, it creates a caret to use, and then when it loses the focus, it destroys its caret. Obviously, if you don't do any of this manually, you will receive the default implementation.

Now, the sample code. Because I like candy machine interfaces, I'd wrap it in a function:

bool CreateCustomCaret(HWND hWnd, int width, int height, int x, int y)
{
    // Create the caret for the control receiving the focus.
    if (!CreateCaret(hWnd,    /* handle to the window that will own the caret */
                     NULL,    /* create a solid caret using specified size    */
                     width,   /* width of caret, in logical units             */
                     height)) /* height of caret, in logical units            */
        return false;

    // Set the position of the caret in the window.
    if (!SetCaretPos(x, y))
        return false;

    // Show the caret. It will begin flashing automatically.
    if (!ShowCaret(hWnd))
        return false;

    return true;
}

Then, in response to WM_SETFOCUS, EN_SETFOCUS, or a similar notification, I would call the CreateCustomCaret function. And in response to WM_KILLFOCUS, EN_KILLFOCUS, or another similar notification, I would call DestroyCaret().

Alternatively, CreateCustomCaret could have created the caret from a bitmap. I might provide the following overload:

bool CreateCustomCaret(HWND hWnd, HBITMAP hbmp, int x, int y)
{
    // Create the caret for the control receiving the focus.
    if (!CreateCaret(hWnd,   /* handle to the window that will own the caret   */
                     hBmp,   /* create a caret using specified bitmap          */
                     0, 0))  /* width and height parameters ignored for bitmap */
        return false;

    // Set the position of the caret in the window.
    if (!SetCaretPos(x, y))
        return false;

    // Show the caret. It will begin flashing automatically.
    if (!ShowCaret(hWnd))
        return false;

    return true;
}