Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Клуб профессиональных программистов :: Выпуск #14




На нашем форуме накопилось немало ответов на многие вопросы по программированию. Для начинающих это может быть хорошей помощью. Поиск - великое дело, но ответ на нужный вопрос, зачастую, находится в дискуссии по совсем другой теме. Для облегчения поиска мы переработали часть тем форума и сделали набор вопрос-ответов (ЧАВО или FAQ). Его можно увидеть по этой ссылке: http://forum.shelek.com/index.php/board,114.0.html.

Публикуем несколько вопросов оттуда.

FAQ по Win32 API и Visual C++.

A: Все в реестре. В HKEY_CLASSES_ROOT\CLSID\ записан GUID.

В HKEY_CLASSES_ROOT\<ProgID компонента>\CLSID есть информация о расположении файла, о версии компонента и т.п. В реестр лазить API функцией RegQueryValueEx() .

A: Есть два пути решения.

1) Проецируемые в память файлы (с доступом чтение/запись). Книга: Д. Рихтер "Виндовс для проффесионалов" Глава 17.

2) Разделяемые переменные. Та же глава.

Код:

//Здесь создаём свой сегмент данных. Переменные должны
//быть обязательно инициализированы и помешены между
//двумя pragma data_seg. Иначе они не войдут в данный
//сегмент.
#pragma data_seg("Shared") LONG g_lInstanceCount = 0;
#pragma data_seg()

//теперь только осталось указать компилятору свойства
//этого сегмента
#pragma comment(linker, /SECTION Shared,RWS );

Есть другой путь принудительного включения в сегмент, но сегмент уже должен быть упомянут ранее.

Код:

__declspec(allocate("Shared")) int с = 0;

A: От координат на экране нужно отнять величины сдвига, заданные в данный момент полосами прокруток.

Более подробно:

При нулевых положениях полос прокруток левый верхний угол окна имеет логические координаты 0,0. Скажем, при щелчке по окну в обработчик OnLButtonDown пришли координаты X,Y. Для определения действительных значений координат берём текущие значения сдвига окна, заданные полосами прокруток (dX,dY), и отнимаем от координат X,Y.

Код:

void CMyScrollView::OnLButtonDown(UINT nFlags, CPoint point) 
{
 POINT pnt = GetScrollPosition();
 //или
 //CPoint pnt = GetScrollPosition();
 long Xw=point.x-pnt.x;
 long Yw=point.y-pnt.y;
 
 //Если теперь нарисовать на окне точку Xw,Yw, то на
 //экране точка будет выведена в точности под курсором
 CDC* pdc=GetDC();
 pdc->SetPixel(Xw,Yw,RGB(0,0,0));
 ReleaseDC(pdc);
 
 CScrollView::OnLButtonDown(nFlags, point);
}

A: Проще всего выбрать моноширный шрифт, например Courier, Courier New, Lucida Console, Terminal.

A: Используя функцию API, проецирующую точки одного окна на другое.

Код:

WINUSERAPI int WINAPI MapWindowPoints(
 HWND hWndFrom,  //хендл окна "откуда"
 HWND hWndTo,  //хендл окна "куда"
 LPPOINT lpPoints, //указатель на массив POINT[]
 UINT cPoints);  //размер массива

 // Для абсолютных координат задать хендл==0 или HWND_DESKTOP

Или аналогичные функции MFC класса CWnd.

Код:

// HWND_DESKTOP

void MapWindowPoints(
 CWnd* pwndTo,
 LPPOINT lpPoint,
 UINT nCount) const;

void MapWindowPoints(
 CWnd* pwndTo,
 LPRECT lpRect) const;

// Для абсолютных координат задать pwndTo==0

Например, определяем, какие относительные координаты имеет текущее положение курсора в окне, адрес которого содержится в указателе CWnd* pWnd.

Код:

//определяем абсолютные координаты, текущего
//положения курсора
POINT pnt;
::GetCursorPos(&pnt);
 
//проецируем на окно *pWnd (через API функцию)
::MapWindowPoints(HWND_DESKTOP,pWnd->m_hWnd,&pnt,1);
 
//pnt - относительные координаты

FAQ по ANSI C++.

A: Стандартный прием - задание точности.

Код:

#include <math.h>
double d1,d2;
double acc=0.00001;//требуемая точность сравнения
 ...
 ...
if( fabs(d1-d2) < acc )
{
 //операнды равны (с точностью acc)
}
else
{
 //убедились, что операнды не равны, здесь можно
 //смело сравнивать операторами ">" и "<"
}

A: Вот примеры для разных случаев.

Код:

char sDouble[128]
float d1 = 0.001778;
 ...
sprintf(sDouble,"%.4f",d1);//4 знака после запятой
 ...
printf("%.4f", d1);//4 знака после запятой
 ...
cout<<setiosflags( ios::fixed )<< setprecision( 4 ) << d1;//4 знака после запятой

A: Если нужно вывести, к примеру, double с 5 знаками после десятичной точки, сначала нужно сформировать строку вида "%.5f", а потом задать ее в качестве спецификации формата.

Код:

char sDouble[128], strFormat[128];
double d1 = 150.0f;
int nCount;//текущее количество знаков после запятой
 ...
nCount = 5;
sprintf(strFormat, "%%.%df", nCount );
//strFormat теперь содержит строку "%.5f"
//форматируем:
sprintf(sDouble, strFormat, d1);

Аналогично, если используется класс CString.

Код:

CString sDouble,strFormat;
 ...
strFormat.Format("%%.%df", nCount );
sDouble.Format(strFormat, d1);

A: В printf в спецификаторе числа разрядов можно поставить символ "*". Тогда соответствующий по порядку аргумент будет интерпретирован как число знаков.

Код:

printf("%.*f", 2, 3.1415);//выведет 3.14

(для CString::Format символ "*" НЕ работает)

A: Можно перенаправить поток cout при запуске программы, но тогда ВСЕ сообщения пойдут в этот файл. Так что лучше открыть специальный поток для файла.

Код:

#include <fstream>
 ...
ofstream file_out (filename);
 ...
file_out<< "текст" <<setiosflags( ios::fixed ) <<setprecision( 3 )<< 3.456564 << endl;


А теперь прощаемся с Вами до следующего выпуска.

                                        С уважением, команда Клуба.




В избранное