Помощь - Поиск - Пользователи - Календарь
Полная версия: общие вопросы по WINAPI
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
Client
function windowproc(wnd:hwnd; msg,wparam,lparam:LongInt):LongInt; stdcall;
begin
case msg of
WM_DESTROY: begin
PostQuitMessage(0);
Result:=0;
exit;
end;
end;
Result:=DefWindowProc(wnd,msg,wparam,lparam)
end;
Вот простая оконная процедура, которая реагирует на выход. Зачем нужно
Result:=0;
и сразу после этого EXIT и после case
Result:=DefWindowProc(wnd,msg,wparam,lparam)
?
volvo
Ты ловишь нужное тебе сообщение, и обрабатываешь его. После этого надо выйти из обработчика, так? Вот и возвращается 0, чтобы показать, что сообщение уже обработано. А если поступило сообщение, которое ты НЕ предусмотрел (или не хочешь обрабатывать), то вызывается DefWindowProc - дефолтный обработчик сообщений окна. Именно в нем стандартно обрабатываются все изменения размеров окна, минимизация/максимизация, перетаскивание окна по десктопу, и т.д... Если будешь обрабатывать ВСЕ без исключения сообщения Windows, связанные с твоим окном - с ума сойдешь, их сотни, если не тысячи smile.gif
Client
Result:=DefWindowProc(wnd,msg,wparam,lparam)
Без нее даже не запустилась программа smile.gif
hIcon:=loadicon (0, IDI_APPLICATION);
hCursor:=loadcursor(0, IDC_ARROW);
А как загрузить другой курсор и иконку?
volvo
Цитата
Без нее даже не запустилась программа
Потому что WM_CREATE и WM_PAINT остались необработанными smile.gif

Цитата
А как загрузить другой курсор и иконку?
Добавить к проекту RC-файл, в нем описАть иконку:
101 ICON "Icon.ico"
, и подключить ее:

const
IDI_MyOwnIcon = 101; // <--- должно совпадать с ID в файле ресурсов

...
hIcon := LoadIcon(GetModuleHandle(nil), MAKEINTRESOURCE(IDI_MyOwnIcon));
То же самое - с курсором...
Client
а как добавить этот файл? PROJECT- add... ?
volvo
Если он у тебя уже есть, то добавить можно через Project->Add. Если нет - то создай (через Windows Explorer) пустой файл в папке с проектом (с расширением RC), и добавляй его...
Client
создал файл и через блокнот в него добавил
101 ICON "Icon.ico"
Призапуске ругается на эту строчку
volvo
А файл с иконкой (тот самый Icon.ico) где? Ты же хочешь свою иконку, а не стандартную, значит, она должна у тебя быть.
Client
Списибо!
курсор получился)
Client
Вот я создал меню с пунктами и при нажатии на них выскакивает сообщение. А как при выборе пункта меню осуществить нажатие другого пункта? или вообще кнопки (что-то вроде Button2.click(sender))
volvo
Цитата
А как при выборе пункта меню осуществить нажатие другого пункта?
Не понял. Что, вместо одного пункта заставить программу думать, что был нажат другой? Тогда просто пошли (SendMessage) ID второго пункта окну. Когда окно его получит, тогда и обработает.

С кнопкой - аналогично, посылай ее ID (когда создаешь кнопку через CreateWindowEx, третий от конца параметр - это и есть её ID) своему же окну. Только зачем тебе это - непонятно. Не проще нажать на кнопку?
Client
У SendMessage же 4 параметра - hwnd, msg, и 2 параметра. Как тут быть?
volvo
SendMessage(hWnd, WM_COMMAND, btnID, 0);

как раз 4, почему у тебя этот вопрос возник?
Client
Цитата
почему у тебя этот вопрос возник?
я думал надо
SendMessage(btn,?,0,0);
и команду не знал.
Client
по поводу сабклассинга я не понял как работают функции SetWindowLong, CallWindowProc, GetWindowLong.
Цитата
Для вызова оконной процедуры по её адресу используется функция CallWindowProc
Цитата
SetWindowLong. Вообще, эта функция предназначена для изменения определённого атрибута окна
С вингарда.
volvo
Что непонятно с этими функциями? Ну, устанавливает она атрибут окна, это все, что тебе надо о ней знать. Как работает CreateWindow или GetDC тебе понятно? Оно тебе не надо на данном этапе.

Вот описание второй функции по-русски: Функция SetWindowLong, а CallWindowProc просто вызывает оконную функцию, передаваемую ей в первом параметре. Зачем это нужно? Ну, допустим, ты написал свою процедуру обработки тех сообщений, которые тебе нужны, обработал их. А что дальше? Те, которые НЕ обрабатываются твоей процедурой, что, будут потеряны? Нет, ты просто берешь адрес старой (настоящей, неподмененной) оконной процедуры того окна, которое сабклассируешь, и вызываешь ее.

Помнишь, что произошло, когда ты не вызвал DefWindowProc для своего окна? Вот примерно то же самое будет, если не вызвать старую процедуру сабклассированного окна. Ты-то перехватил все, что тебе надо было, а мало ли что окно еще обрабатывает... Вот и пусть обрабатывает само, тебе-то это зачем?

Подобная техника применяется при написании обработчиков прерываний (никогда не делал? smile.gif ) - пишешь свой обработчик, скажем, таймера, выполняешь что-то свое, а потом вызываешь прежний, системный обработчик...
Client
{ Модифицированная оконная процедура поля ввода }
function EditWinProc(hWnd: HWND; uMsg: UINT;
wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
case uMsg of
{ Запрещаем показ контекстного меню }
WM_CONTEXTMENU:
begin
Result := 0;
MessageBeep(0);
Exit; // тут выходим из всей процедуры или из case?
end;
end;
{ Не забываем вызвать оригинальную оконную процедуру }
Result := CallWindowProc(Pointer(GetWindowLong(hWnd, GWL_USERDATA)),
hWnd, uMsg, wParam, lParam);
end;
{Модифицированная оконная процедура кнопки }
function BtnWinProc(hWnd: HWND; uMsg: UINT;
wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
case uMsg of
{ При нажатии мыши запускаем таймер, интервал - 10 миллисекунд }
WM_LBUTTONDOWN: SetTimer(hWnd, BtnTimer, 10, @BtnTimerProc);

{ При отпускании мыши уничтожаем таймер }
WM_LBUTTONUP:
begin
KillTimer(hWnd, BtnTimer);
{ Восстанавливаем прежний текст }
SetWindowText(hWnd, BtnText);
end;
end;
{ Не забываем вызвать оригинальную оконную процедуру }
Result := CallWindowProc(Pointer(GetWindowLong(hWnd, GWL_USERDATA)),
hWnd, uMsg, wParam, lParam);
end;
В 1 функции - если произошло нужное событие, то выполняем что надо и EXit- выход из функции. А во 2 функции, если в оригинальной оконной процедуре есть обработчик WM_LBUTTONDOWN то выполнится работа с таймером а потом и другое? Тут EXIT'а нету wacko.gif

Добавлено через 4 мин.
Цитата
Как работает CreateWindow или GetDC тебе понятно?
С помощью CreateWindow нашел как создавать окно, кнопку, edit, label. Чекбокс и радио еще в процессе smile.gif
Цитата
никогда не делал?
нет (еще нет smile.gif )
volvo
Цитата
А во 2 функции, если в оригинальной оконной процедуре есть обработчик WM_LBUTTONDOWN то выполнится работа с таймером а потом и другое?
Ну, раз ты написал БЕЗ Exit-а, значит, да. И твоя функция отследит события, и потом еще передаст их в оригинальную функцию окна. А что тебя так удивляет? Ты же пишешь модифицированную функцию, может тебе не надо ничего менять, только ДОБАВИТЬ кое-что к существующему обработчику. Вот и добавляешь. А события пропускаешь дальше, пускай их оригинальная функция обрабатывает, у нее это лучше получится smile.gif ...
Client
Спасибо,понял. Теперь можно и спать идти smile.gif
Client
Привет
По поводу суперклассинга - берем уже имеющийся класс, меняем его, указав новую процедуру, регистрируем класс и создаем окна нового класса. При выходе удаляем класс. Правильно понял?
volvo
Правильно... Осталось теперь реализовать smile.gif
Client
я пока по примеру с вингарда smile.gif
А на изменение размера формы какое сообщение поступает? на WM_RESIZE ругается. Возможно wm_size?
volvo
Это смотря когда... Во время изменения размера постоянно приходит WM_SIZING; сразу после того, как пользователь отпустил мышу (размер установлен окончательно) - приходит WM_SIZE.
Client
Спасиб, показываю координаты окна при передвижении и ресайзе
Вот попробовал добавить кнопку в другое окно, и хоть для меня странно, но получилось smile.gif И какие еще чтучки можно сделать? smile.gif
А можно создать кнопку скругленной или вообще другой формы?
И почему после выхода из моей программы кнопка удаляется?
volvo
Цитата
почему после выхода из моей программы кнопка удаляется?
Хм... Ну, ты же в своей программе регистрируешь класс, и потом его удаляешь? Удалил класс - удалились все объекты этого класса.

Цитата
А можно создать кнопку скругленной или вообще другой формы?
Легко:
Создание круглой кнопки на WinAPI, можно и вообще любой формы, тогда понадобится работать с регионами. Где-то на RSDN еще была статья, если я не ошибаюсь.

Цитата
И какие еще чтучки можно сделать?
Ну, это зависит только от твоей фантазии.
Client
Цитата
Удалил класс - удалились все объекты этого класса.
А если не удалять класс утечки памяти не будет? И что такое Instance и HInstance?
volvo
А если ты класс создал, значит должен удалить:
Цитата(MSDN)
Remarks
Before calling this function, an application must destroy all windows created with the specified class.
All window classes that an application registers are unregistered when it terminates.


Цитата
И что такое Instance и HInstance?
Вообще Instance - это Экземпляр. Все остальное - только по коду, телепатия на других форумах. Назвать переменную я могу как хочу, могу вообще hInstance обозвать счетчик цикла.
Client
При создании класса
hInstance := hInstance;
Хотя у меня нету переменной hInstance. В коде когда навожу мышу показыват что вроде как системная константа blink.gif
volvo
Цитата
Хотя у меня нету переменной hInstance
Мало ли, чего у тебя нету. Зато в модуле SysInit она есть, это ID твоей программы.
Client
Спасибо за ответы.
Еще пара вопросов и все smile.gif
Суперклассинг. В примере на вингарде создавали едиты и они удалялись при нажатии на них. Тут модернизировали класс едита. А если уже есть эти же самые едиты и на них надо поставить обработчик на нажатие клавиши, то тут как быть? не переделывать класс?
И сабклассинг другого приложения. Есть пример для новичка? Засабклассировать кнопку или едит, а там пример, половина написана на ассемблере. Для меня "без шансов" sad.gif
volvo
Цитата
Суперклассинг. В примере на вингарде создавали едиты и они удалялись при нажатии на них. Тут модернизировали класс едита. А если уже есть эти же самые едиты и на них надо поставить обработчик на нажатие клавиши, то тут как быть?
Использовать Сабклассинг: "контроль сообщений окон путем модификации оконной процедуры последних". Пишешь свою оконную функцию, которая обработает события WM_KEYUP/WM_KEYDOWN/WM_CHAR (обычно обработка нажатия клавиши сводится к WM_KEYDOWN), а все остальные события "пропустит" оригинальной оконной функции. И вызываешь свою функцию вместо оригинальной. Суперклассинг здесь не нужен.
Client
Т.е. надо сабклассировать каждый едит?
volvo
Для каждого EDIT-а, для которого надо поймать нажатия, придется подменить оконную функцию. Ты это хотел услышать?
Client
Да. Списибо!
Client
#include "stdafx.h"
#include "iostream.h"
#include "afxwin.h"

void main()
{
HWND hwnd;
hwnd = GetDesktopWindow();
HDC hdc;
hdc=GetWindowDC(hwnd);
int i;
cin >> i;
CPen pen(PS_SOLID,4,RGB(255,0,0));
SelectObject(hdc,pen);
Ellipse(hdc,-100,-100,100,100);
}
Как будет выглядеть на дельфи эта часть кода
int i; // описание типа integer
cin >> i; //типа read (i) ?
CPen pen(PS_SOLID,4,RGB(255,0,0));
volvo
Ну поскольку введенное i нигде не используется, то и на фиг оно не надо... А все остальное - вот так, например:

var
myDC: HDC;
ps: PAINTSTRUCT;

myPen: HPEN;
...
case AMessage of
WM_PAINT:
begin
myDC := BeginPaint(Window, ps);
myPen := CreatePen(PS_SOLID, 4, RGB(255, 0, 0));
SelectObject(myDC, myPen);
Ellipse(myDC, -100, -100, 100, 100);
EndPaint(Window, ps);
Exit(0);
end;
...
правда, много изменений? smile.gif Только вот мой кусок - рабочий, а твой - вряд ли...
Client
Цитата
а твой - вряд ли...
взял отсюда
Спасибо
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.