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

  • Автор темы pudra
  • Дата начала
Статус
Закрыто для дальнейших ответов.
P

pudra

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

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

????

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

Книга не у всех есть :)
 
P

pudra

#3
да сейчас кину
кидаю не весь код.... а только там где правил... после создания однодокументной (SDI) программы.
class CCaretsDoc : public CDocument
{
protected: // create from serialization only
CCaretsDoc();
DECLARE_DYNCREATE(CCaretsDoc)

// Attributes
public:

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCaretsDoc)
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CCaretsDoc();
CString StringData; //ДОБАВИЛ ЭТУ СТРОКУ
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
//{{AFX_MSG(CCaretsDoc)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

////////////////////////

в конструкторе документа

CCaretsDoc::CCaretsDoc()
{
// TODO: add one-time construction code here
StringData = ""; //ДОБАВИЛ ЭТУ СТРОКУ
}

//////////////////////

потом добавил WM_CHAR

void CCaretsView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
CCaretsDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

pDoc->StringData += nChar; //ДОБАВИЛ ЭТУ СТРОКУ
Invalidate(); //ДОБАВИЛ ЭТУ СТРОКУ

CView::OnChar(nChar, nRepCnt, nFlags);
}

////////////////////////////////////

далле идет определине параметров шрифта по стркутуре TEXTMETRIC

файл // caretsView.h : interface of the CCaretsView class

class CCaretsView : public CView
{
protected: // create from serialization only
CCaretsView();
DECLARE_DYNCREATE(CCaretsView)
CPoint CaretPosition; //ДОБАВИЛ ЭТУ СТРОКУ
boolean CaretCreated; //ДОБАВИЛ ЭТУ СТРОКУ

// Attributes
public:
CCaretsDoc* GetDocument();

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CCaretsView)
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CCaretsView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
//{{AFX_MSG(CCaretsView)
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

////////////////////////

void CCaretsView::OnDraw(CDC* pDC)
{
CCaretsDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);

if(!CaretCreated) //ДОБАВИЛ ЭТУ СТРОКУ
{
TEXTMETRIC textmetric; //ДОБАВИЛ ЭТУ СТРОКУ
pDC->GetTextMetrics(&textmetric); //ДОБАВИЛ ЭТУ СТРОКУ
CreateSolidCaret(textmetric.tmAveCharWidth/8, textmetric.tmHeight); //ДОБАВИЛ ЭТУ СТРОКУ
CaretPosition.x = CaretPosition.y = 0; //ДОБАВИЛ ЭТУ СТРОКУ

SetCaretPos(CaretPosition); //ДОБАВИЛ ЭТУ СТРОКУ
ShowCaret(); //ДОБАВИЛ ЭТУ СТРОКУ
CaretCreated = true; //ДОБАВИЛ ЭТУ СТРОКУ

}
// TODO: add draw code for native data here
}
вот собственно
надеюсь будет понятно:) старался максимально информативно описать:)
 
M

mike.dld

#4
SetCaretPos() вижу, ShowCaret() вижу, а вот CreateCaret() почему-то нет :)
 
P

pudra

#5
<!--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() должен быть?
 
P

pudra

#9
работает но не полностью... курсор установлен в начале.... но если набрать текст он пропадает
 
P

pudra

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

mike.dld

#11
За тебя его никто не переместит. И вообще - нужно вводить текст - используй EDIT с ES_MULTILINE, или RICHEDIT.
 
A
#13
Не знаю, не будет ли это слишком много, но вот соответствующий раздел из книги Петзольда. Непомню где ее качал.

Каретка (не курсор)
Когда вы в программе набираете текст, обычно маленький символ подчеркивания или маленький четырехугольник
показывает вам место, где следующий набираемый вами символ появится на экране. Вы можете считать, что это
курсор (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
© 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 меняется
содержимое буфера, а затем в окне рисуется новый символ или символы.
 
Статус
Закрыто для дальнейших ответов.