создание курсора в окне

Тема в разделе "MS Visual C++", создана пользователем pudra, 28 июн 2005.

Статус темы:
Закрыта.
  1. pudra

    pudra Гость

    сделал пример по книге визуал 6 С. Холзнер
    никакого курсора не видно. может подскажите где моно найти пральный пример?

    сайчес займусь и сам поиском.
     
  2. ????

    ???? Гость

    Для: pudra
    ты хоть пример того, что не получается кинь.

    Книга не у всех есть :)
     
  3. pudra

    pudra Гость

    да сейчас кину
    кидаю не весь код.... а только там где правил... после создания однодокументной (SDI) программы.
    вот собственно
    надеюсь будет понятно:) старался максимально информативно описать:)
     
  4. mike.dld

    mike.dld Гость

    SetCaretPos() вижу, ShowCaret() вижу, а вот CreateCaret() почему-то нет :)
     
  5. pudra

    pudra Гость

    <!--QuoteBegin-mike.dld+29:06:2005, 01:25 -->
    <span class="vbquote">(mike.dld @ 29:06:2005, 01:25 )</span><!--QuoteEBegin-->SetCaretPos() вижу, ShowCaret() вижу, а вот CreateCaret() почему-то нет :)
    [snapback]21727" rel="nofollow" target="_blank[/snapback]​
    [/quote]

    в каком месте кода CreateCaret() должен быть?
     
  6. mike.dld

    mike.dld Гость

    Сорри, ошибся насчёт CreateCaret ошибся :)
     
  7. pudra

    pudra Гость

    вопрос еще актуален
     
  8. mike.dld

    mike.dld Гость

    То, что я тебе объяснил, у меня работает.
     
  9. pudra

    pudra Гость

    работает но не полностью... курсор установлен в начале.... но если набрать текст он пропадает
     
  10. pudra

    pudra Гость

    мне нужно что курсор был полноценный... двигался... с помощью мыши выделял... и т.д. тот вариант кода что ты показал его только устанаваливает в заданной точке.
    в CMainFrame::OnCreate пишу
    Код (Text):
    CreateSolidCaret(2,12);
    SetCaretPos(CPoint(100,100));
    ShowCaret();
     
  11. mike.dld

    mike.dld Гость

    За тебя его никто не переместит. И вообще - нужно вводить текст - используй EDIT с ES_MULTILINE, или RICHEDIT.
     
  12. pudra

    pudra Гость

    попдробнее пжлст
     
  13. alam

    alam Гость

    Не знаю, не будет ли это слишком много, но вот соответствующий раздел из книги Петзольда. Непомню где ее качал.

    Каретка (не курсор)
    Когда вы в программе набираете текст, обычно маленький символ подчеркивания или маленький четырехугольник
    показывает вам место, где следующий набираемый вами символ появится на экране. Вы можете считать, что это
    курсор (cursor), но, если вы программируете для Windows, необходимо отказаться от такого представления. В
    Windows это называется "каретка" (caret). Слово же "курсор" относится к битовому образу, отражающему
    положение мыши на экране.
    Функции работы с кареткой
    Здесь перечислены пять основных функций работы с кареткой:
    • CreateCaret — создает связанную с окном каретку.
    • SetCaretPos — устанавливает положение каретки в окне.
    • ShowCaret — показывает каретку.
    • HideCaret — прячет каретку.
    • DestroyCaret — удаляет каретку.
    Кроме этих, еще имеется функция получения положения каретки (GetCaretPos) и функции установки и получения
    частоты мигания каретки (GetCaretBlinkTime) и (SetCaretBlinkTime).
    Каретка — это обычно горизонтальная черточка или прямоугольник, имеющие размер символа, или вертикальная
    черточка. Вертикальная черточка рекомендуется при использовании пропорционального шрифта, такого как
    задаваемый по умолчанию системный шрифт Windows. Поскольку размер символов пропорционального шрифта
    не фиксирован, горизонтальной черточке и прямоугольнику невозможно задать размер символа.
    191
    Вы не можете просто создать каретку при обработке сообщения WM_CREATE и удалить ее при обработке
    сообщения WM_DESTROY. Каретка — это то, что называется "общесистемным ресурсом" (systemwide resource). Это
    означает, что в системе имеется только одна каретка. И, как результат, программа при необходимости вывода
    каретки на экран своего окна "заимствует" ее у системы.
    Серьезно ли это необычное ограничение? Конечно нет. Подумайте: появление каретки в окне имеет смысл только
    в том случае, если окно имеет фокус ввода. Каретка показывает пользователю, что он может вводить в программу
    текст. В каждый конкретный момент времени только одно окно имеет фокус ввода, поэтому для всей системы и
    нужна только одна каретка.
    Обрабатывая сообщения WM_SETFOCUS и WM_KILLFOCUS, программа может определить, имеет ли она фокус
    ввода. Оконная процедура получает сообщение WM_SETFOCUS, когда получает фокус ввода, а сообщение
    WM_KILLFOCUS, когда теряет фокус ввода. Эти сообщения приходят попарно: оконная процедура получает
    сообщение WM_SETFOCUS всегда до того, как получит сообщение WM_KILLFOCUS, и она всегда получает
    одинаковое количество сообщений WM_SETFOCUS и WM_KILLFOCUS за время существования окна.
    Основное правило использования каретки выглядит просто: оконная процедура вызывает функцию CreateCaret
    при обработке сообщения WM_SETFOCUS и функцию DestroyCaret при обработке сообщения WM_KILLFOCUS.
    Имеется несколько других правил: каретка создается скрытой. После вызова функции CreateCaret, оконная
    процедура должна вызвать функцию ShowCaret, чтобы сделать каретку видимой. В дополнение к этому, оконная
    процедура, когда она рисует в своем окне при обработке сообщения, отличного от WM_PAINT, должна скрыть
    каретку, вызвав функцию HideCaret. После того как оконная процедура закончит рисовать в своем окне, она
    вызывает функцию ShowCaret, чтобы снова вывести каретку на экран. Функция HideCaret имеет дополнительный
    эффект: если вы несколько раз вызываете HideCaret, не вызывая при этом ShowCaret, то чтобы каретка снова стала
    видимой, вам придется такое же количество раз вызвать функцию ShowCaret.
    Программа TYPER
    Программа TYPER, представленная на рис. 5.5, объединяет вместе многое из того, о чем мы узнали в этой главе.
    Программу TYPER можете считать сильно устаревшим текстовым редактором. Вы можете набрать в окне текст,
    перемещая курсор (имеется ввиду каретка) по экрану с помощью клавиш управления курсором (или клавишами
    управления кареткой?), и стереть содержимое окна, нажав <Esc>. Окно также очистится при изменении размеров
    окна. Здесь нет ни прокрутки, ни поиска и замены, ни возможности сохранять файлы, ни контроля правописания,
    но это только начало.
    Для простоты в программе TYPER используется фиксированный шрифт. Создание текстового редактора для
    пропорционального шрифта является, как вы могли бы сообразить, гораздо более трудным делом. Программа
    получает контекст устройства в нескольких местах: при обработке сообщений WM_CREATE, WM_KEYDOWN,
    WM_CHAR и WM_PAINT. Каждый раз при этом для выбора фиксированного шрифта вызываются функции
    GetStockObject и SelectObject.
    При обработке сообщения WM_SIZE программа TYPER рассчитывает ширину и высоту окна в символах и хранит
    эти значения в переменных cxBuffer и cyBuffer. Затем она использует функцию malloc, чтобы выделить буфер для
    хранения всех символов, которые могут быть напечатаны в окне. В переменных xCaret и yCaret сохраняется
    положение каретки в символах.
    При обработке сообщения WM_SETFOCUS программа TYPER вызывает функцию CreateCaret для создания
    каретки, имеющей ширину и высоту символа, функцию SetCaretPos для установки положения каретки и функцию
    ShowCaret, чтобы сделать каретку видимой. При обработке сообщения WM_KILLFOCUS программа вызывает
    функции HideCaret и DestroyCaret.
    TYPER.MAK
    #---------------------
    # TYPER.MAK make file
    #---------------------
    typer.exe : typer.obj
    $(LINKER) $(GUIFLAGS) -OUT:typer.exe typer.obj $(GUILIBS)
    typer.obj : typer.c
    $(CC) $(CFLAGS) typer.c
    TYPER.C
    /*--------------------------------------
    TYPER.C -- Typing Program
    192
    &copy; Charles Petzold, 1996
    --------------------------------------*/
    #include <windows.h>
    #include <stdlib.h>
    #define BUFFER(x,y) *(pBuffer + y * cxBuffer + x)
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    PSTR szCmdLine, int iCmdShow)
    {
    static char szAppName[] = "Typer";
    HWND hwnd;
    MSG msg;
    WNDCLASSEX wndclass;
    wndclass.cbSize = sizeof(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;
    wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    RegisterClassEx(&wndclass);
    hwnd = CreateWindow(szAppName, "Typing Program",
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT, CW_USEDEFAULT,
    CW_USEDEFAULT, CW_USEDEFAULT,
    NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while(GetMessage(&msg, NULL, 0, 0))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    return msg.wParam;
    }
    LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
    {
    static char *pBuffer = NULL;
    static int cxChar, cyChar, cxClient, cyClient, cxBuffer, cyBuffer,
    xCaret, yCaret;
    HDC hdc;
    int x, y, i;
    PAINTSTRUCT ps;
    TEXTMETRIC tm;
    switch(iMsg)
    {
    case WM_CREATE :
    hdc = GetDC(hwnd);
    193
    SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
    GetTextMetrics(hdc, &tm);
    cxChar = tm.tmAveCharWidth;
    cyChar = tm.tmHeight;
    ReleaseDC(hwnd, hdc);
    return 0;
    case WM_SIZE :
    // obtain window size in pixels
    cxClient = LOWORD(lParam);
    cyClient = HIWORD(lParam);
    // calculate window size in characters
    cxBuffer = max(1, cxClient / cxChar);
    cyBuffer = max(1, cyClient / cyChar);
    // allocate memory for buffer and clear it
    if(pBuffer != NULL)
    free(pBuffer);
    if((pBuffer =(char *) malloc(cxBuffer * cyBuffer)) == NULL)
    MessageBox(hwnd, "Window too large. Cannot "
    "allocate enough memory.", "Typer",
    MB_ICONEXCLAMATION | MB_OK);
    else
    for(y = 0; y < cyBuffer; y++)
    for(x = 0; x < cxBuffer; x++)
    BUFFER(x,y) = ' ';
    // set caret to upper left corner
    xCaret = 0;
    yCaret = 0;
    if(hwnd == GetFocus())
    SetCaretPos(xCaret * cxChar, yCaret * cyChar);
    return 0;
    case WM_SETFOCUS :
    // create and show the caret
    CreateCaret(hwnd, NULL, cxChar, cyChar);
    SetCaretPos(xCaret * cxChar, yCaret * cyChar);
    ShowCaret(hwnd);
    return 0;
    case WM_KILLFOCUS :
    // hide and destroy the caret
    HideCaret(hwnd);
    DestroyCaret();
    return 0;
    case WM_KEYDOWN :
    switch(wParam)
    {
    case VK_HOME :
    xCaret = 0;
    break;
    case VK_END :
    194
    xCaret = cxBuffer - 1;
    break;
    case VK_PRIOR :
    yCaret = 0;
    break;
    case VK_NEXT :
    yCaret = cyBuffer - 1;
    break;
    case VK_LEFT :
    xCaret = max(xCaret - 1, 0);
    break;
    case VK_RIGHT :
    xCaret = min(xCaret + 1, cxBuffer - 1);
    break;
    case VK_UP :
    yCaret = max(yCaret - 1, 0);
    break;
    case VK_DOWN :
    yCaret = min(yCaret + 1, cyBuffer - 1);
    break;
    case VK_DELETE :
    for(x = xCaret; x < cxBuffer - 1; x++)
    BUFFER(x, yCaret) = BUFFER(x + 1, yCaret);
    BUFFER(cxBuffer - 1, yCaret) = ' ';
    HideCaret(hwnd);
    hdc = GetDC(hwnd);
    SelectObject(hdc,
    GetStockObject(SYSTEM_FIXED_FONT));
    TextOut(hdc, xCaret * cxChar, yCaret * cyChar,
    & BUFFER(xCaret, yCaret),
    cxBuffer - xCaret);
    ShowCaret(hwnd);
    ReleaseDC(hwnd, hdc);
    break;
    }
    SetCaretPos(xCaret * cxChar, yCaret * cyChar);
    return 0;
    case WM_CHAR :
    for(i = 0; i <(int) LOWORD(lParam); i++)
    {
    switch(wParam)
    {
    case '\b' : // backspace
    if(xCaret > 0)
    {
    xCaret--;
    SendMessage(hwnd, WM_KEYDOWN,
    VK_DELETE, 1L);
    }
    break;
    195
    case '\t' : // tab
    do
    {
    SendMessage(hwnd, WM_CHAR, ' ', 1L);
    }
    while(xCaret % 8 != 0);
    break;
    case '\n' : // line feed
    if(++yCaret == cyBuffer)
    yCaret = 0;
    break;
    case '\r' : // carriage return
    xCaret = 0;
    if(++yCaret == cyBuffer)
    yCaret = 0;
    break;
    case '\x1B' : // escape
    for(y = 0; y < cyBuffer; y++)
    for(x = 0; x < cxBuffer; x++)
    BUFFER(x, y) = ' ';
    xCaret = 0;
    yCaret = 0;
    InvalidateRect(hwnd, NULL, FALSE);
    break;
    default : // character codes
    BUFFER(xCaret, yCaret) =(char) wParam;
    HideCaret(hwnd);
    hdc = GetDC(hwnd);
    SelectObject(hdc,
    GetStockObject(SYSTEM_FIXED_FONT));
    TextOut(hdc, xCaret * cxChar, yCaret * cyChar,
    & BUFFER(xCaret, yCaret), 1);
    ShowCaret(hwnd);
    ReleaseDC(hwnd, hdc);
    if(++xCaret == cxBuffer)
    {
    xCaret = 0;
    if(++yCaret == cyBuffer)
    yCaret = 0;
    }
    break;
    }
    }
    SetCaretPos(xCaret * cxChar, yCaret * cyChar);
    return 0;
    case WM_PAINT :
    hdc = BeginPaint(hwnd, &ps);
    SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
    196
    for(y = 0; y < cyBuffer; y++)
    TextOut(hdc, 0, y * cyChar, & BUFFER(0,y), cxBuffer);
    EndPaint(hwnd, &ps);
    return 0;
    case WM_DESTROY :
    PostQuitMessage(0);
    return 0;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
    }
    Рис. 5.5 Программа TYPER
    Сообщения WM_KEYDOWN и WM_KEYUP здесь обрабатываются более полно. Обработка сообщения
    WM_KEYDOWN в основном включает в себя обработку клавиш управления курсором. Клавиши <Home> и <End>
    заставляют каретку переместиться в начало или конец строки, клавиши <PageUp> и <PageDown> — к верхней или
    нижней границе окна. Клавиши стрелок работают так, как вы и ожидаете. При нажатии клавиши <Delete>
    программа TYPER должна переместить все, что находится в буфере, начиная от следующей позиции каретки и до
    конца строки, а затем вывести на экран в конец строки символ пробела.
    Обработчик сообщения WM_CHAR включает в себя обработку клавиш <Backspace>, <Tab>, <Linefeed>
    (<Ctrl>+<Enter>), <Enter>, <Escape> и символьных клавиш. Отметьте, что поле Repeat Count параметра lParam
    использовано при обработке сообщения WM_CHAR (здесь предполагается, что важен каждый вводимый
    пользователем символ), а не при обработке сообщения WM_KEYDOWN (чтобы предотвратить нечаянное двойное
    нажатие). Обработка нажатий <Backspace> и <Tab> отчасти упрощена путем использования функции SendMessage.
    Логика обработки клавиши <Backspace> заменяется логикой обработки <Delete>, а клавише <Tab> ставится в
    соответствие несколько пробелов.
    Как уже упоминалось, во время рисования в окне при обработке отличного от WM_PAINT сообщения, вы должны
    сделать каретку невидимой. В программе это делается при обработке сообщения WM_KEYDOWN для клавиши
    <Delete> и сообщения WM_CHAR для символьных клавиш. В обоих этих случаях, в программе TYPER меняется
    содержимое буфера, а затем в окне рисуется новый символ или символы.
     
Загрузка...
Статус темы:
Закрыта.

Поделиться этой страницей