Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Курсор над кнопкой 
:(
    Опции темы
Dmitry_177
Дата 5.3.2007, 20:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Создаю кнопки с флагом BS_OWNERDRAW, чтобы самому перерисовывать их в WM_DRAWITEM..

По идее в структуре DrawItemStruct, т.е. так:
Код

(PDrawItemStruct(lParam)^.itemState and ODS_HOTLIGHT) <> 0


если это выполняется то курсор над кнопкой, но так почему-то не работает... А с пунктами меню так работает.. Как мне тогда определить над кнопкой ли курсор, чтобы перерисовать кнопку?
PM MAIL   Вверх
Snowy
Дата 5.3.2007, 21:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



PM MAIL   Вверх
Dmitry_177
Дата 5.3.2007, 21:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Я создаю кнопку функцией CreateWindow('BUTTON'...)

Добавлено @ 21:23 
Вообще сама программа на одном WinAPI
PM MAIL   Вверх
Snowy
Дата 5.3.2007, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



PM MAIL   Вверх
Dmitry_177
Дата 5.3.2007, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Это я же автор этой темы... smile  Ненравится мне этот метод... smile  Может как-то можно сделать так как это работает с меню?

Добавлено @ 21:50 
Может есть какойнибудь другой способ?

Это сообщение отредактировал(а) Dmitry_177 - 5.3.2007, 21:49
PM MAIL   Вверх
Dmitry_177
Дата 6.3.2007, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Надо использовать функцию TrackMouseEvent? Если да, то помогите примером пожалуйста, что-то я не пойму как она работает...  smile 
PM MAIL   Вверх
Dmitry_177
Дата 6.3.2007, 17:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Я как понимаю функция срабатывает ОДИН раз, где-то вычитал что в сообщении WM_MOUSELEAVE нужно устанавливать функцию на TME_HOVER, а в WM_MOUSEHOVER на TME_LEAVE, т.е. чтобы одно сообщение вызывало на другую.. Т.е. примерно так:

Код

function WindowProc(Window: HWnd; Message: Cardinal; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  tme: TTRACKMOUSEEVENT;
...
    case Message of
      WM_MOUSELEAVE: begin
                      tme.cbSize := SizeOf(TTRACKMOUSEEVENT);
                      tme.dwFlags := TME_HOVER;
                      tme.hwndTrack := Window;
                      tme.dwHoverTime := HOVER_DEFAULT;
                      TrackMouseEvent(tme);
                      // действия, когда курсор вышел за границы..
                     end;

      WM_MOUSEHOVER: begin
                      tme.cbSize := SizeOf(TTRACKMOUSEEVENT);
                      tme.dwFlags := TME_LEAVE;
                      tme.hwndTrack := Window;
                      tme.dwHoverTime := HOVER_DEFAULT;
                      TrackMouseEvent(tme);
                      // действия, когда курсор зашел в пределы..
                     end;


Но вопрос в том, как ее изначально вызвать? Ведь сообщения WM_MOUSELEAVE и WM_MOUSEHOVER сами ниоткуда то не придут...
PM MAIL   Вверх
Dmitry_177
Дата 7.3.2007, 20:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Выложу тестовый проект, если кто сможет помогите плиз.. А то у меня не получается.. smile 

Присоединённый файл ( Кол-во скачиваний: 11 )
Присоединённый файл  TestButton.zip 12,48 Kb
PM MAIL   Вверх
ama_kid
Дата 8.3.2007, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 19
Всего: 95



Цитата(Dmitry_177 @  6.3.2007,  17:19 Найти цитируемый пост)
Но вопрос в том, как ее изначально вызвать? Ведь сообщения WM_MOUSELEAVE и WM_MOUSEHOVER сами ниоткуда то не придут... 

А для чего дано сообщение WM_MOUSEMOVE?
Код

       WM_MOUSEMOVE:
                  begin
                    tme.cbSize:= sizeof(TTRACKMOUSEEVENT);
                    tme.dwFlags:= TME_HOVER or TME_LEAVE;
                    tme.dwHoverTime := HOVER_DEFAULT;
                    tme.hwndTrack := Window;
                    TrackMouseEvent(tme);
                      // действия, когда курсор гуляет по форме...
                  end;
     WM_MOUSELEAVE: begin
                      tme.cbSize := SizeOf(TTRACKMOUSEEVENT);
                      tme.dwFlags := TME_HOVER;
                      tme.hwndTrack := Window;
                      tme.dwHoverTime := HOVER_DEFAULT;
                      TrackMouseEvent(tme);
                       // действия, когда курсор вышел за границы..
                     end;
      WM_MOUSEHOVER: begin
                      tme.cbSize := SizeOf(TTRACKMOUSEEVENT);
                      tme.dwFlags := TME_LEAVE;
                      tme.hwndTrack := Window;
                      tme.dwHoverTime := HOVER_DEFAULT;
                      TrackMouseEvent(tme);
                      // действия, когда курсор зашел в пределы..
                     end;

После этого тебе будут приходить и mouseleave и mousehover


--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
Dmitry_177
Дата 11.3.2007, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 418
Регистрация: 22.9.2006

Репутация: нет
Всего: нет



Попробовал я вобщем так сделать, вроде работает.. Но блин, пропала прорисовка кнопки при нажатии на нее, я ее обрабатывал в WM_DRAWITEM главной процедуре окна, т.е. в WindowProc. Может из за сабклассинга уже не доходит WM_DRAWITEM главному окну??? Вот весь код тестового проекта:

Код

program TestButton;

uses
  Windows,
  Messages;

const
  WindowName            = 'TestButton';
  ID_TestBtn            = 10;

var
  WindowClass: TWndClass;
  hWindow: HWND;
  hTestBtn: HWND;
  AMessage: TMsg;
  old_proc: Pointer;
  bNextButtonTrack: boolean = false;
  tme: tagTRACKMOUSEEVENT;

function ButtonProc(Window: HWnd; Message: Cardinal; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  DC: HDC;
  PStruct: PAINTSTRUCT;
  Pen: HPEN;
  Brush: HBRUSH;
  SelObjPn: HGDIOBJ;
  SelObjBr: HGDIOBJ;
begin
  case Message of
    WM_MOUSEMOVE: begin
                    if not bNextButtonTrack then
                      begin
                        tme.cbSize := SizeOf(tagTRACKMOUSEEVENT);
                        tme.hwndTrack := Window;
                        tme.dwFlags := TME_LEAVE;
                        tme.dwHoverTime := HOVER_DEFAULT;
                        bNextButtonTrack := TrackMouseEvent(tme);

                        InvalidateRect(Window, nil, true);
                      end;
                  end;

    WM_MOUSELEAVE: begin
                    bNextButtonTrack := false;
                    InvalidateRect(Window, nil, true);
                  end;

    WM_PAINT: begin
                if bNextButtonTrack then
                  begin
                    DC := BeginPaint(Window, PStruct);

                    Pen := CreatePen(PS_SOLID, 1, $00000000);
                    SelObjPn := SelectObject(DC, Pen);
                    Brush := CreateSolidBrush($0000FF00);
                    SelObjBr := SelectObject(DC, Brush);

                    Rectangle(DC, PStruct.rcPaint.Left, PStruct.rcPaint.Top, PStruct.rcPaint.Right, PStruct.rcPaint.Bottom);

                    SelectObject(DC, SelObjPn);
                    DeleteObject(Pen);
                    SelectObject(DC, SelObjBr);
                    DeleteObject(Brush);

                    EndPaint(Window, PStruct);
                  end
                else
                  begin
                    DC := BeginPaint(Window, PStruct);

                    Pen := CreatePen(PS_SOLID, 1, $00000000);
                    SelObjPn := SelectObject(DC, Pen);
                    Brush := CreateSolidBrush($00FFFFFF);
                    SelObjBr := SelectObject(DC, Brush);

                    Rectangle(DC, PStruct.rcPaint.Left, PStruct.rcPaint.Top, PStruct.rcPaint.Right, PStruct.rcPaint.Bottom);

                    SelectObject(DC, SelObjPn);
                    DeleteObject(Pen);
                    SelectObject(DC, SelObjBr);
                    DeleteObject(Brush);

                    EndPaint(Window, PStruct);
                  end;
              end;
  end;

  Result := CallWindowProc(old_proc, Window, Message, wParam, lParam);
end;

function WindowProc(Window: HWnd; Message: Cardinal; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  Pen: HPEN;
  Brush: HBRUSH;
  SelObjPn: HGDIOBJ;
  SelObjBr: HGDIOBJ;
begin
  Result := 0;
    case Message of
      WM_CREATE: begin
                  hTestBtn := CreateWindow('BUTTON', 'TestButton', BS_OWNERDRAW or WS_CHILD or WS_VISIBLE, 20, 20, 30, 32, Window, ID_TestBtn, HInstance, nil);

                  old_proc := Pointer(GetWindowLong(Window, GWL_WNDPROC));
                  SetWindowLong(hTestBtn, GWL_WNDPROC, LongInt(@ButtonProc));
                end;

      WM_DRAWITEM: begin
                    with PDrawItemStruct(lParam)^ do
                      begin
                        FrameRect(hDC, rcItem, GetStockObject(WHITE_BRUSH));
                        if (itemState and ODS_SELECTED) <> 0 then
                          begin
                            Pen := CreatePen(PS_SOLID, 1, $00000000);
                            SelObjPn := SelectObject(hDC, Pen);
                            Brush := CreateSolidBrush($000000FF);
                            SelObjBr := SelectObject(hDC, Brush);

                            Rectangle(hDC, rcItem.Left, rcItem.Top, rcItem.Right, rcItem.Bottom);

                            SelectObject(hDC, SelObjPn);
                            DeleteObject(Pen);
                            SelectObject(hDC, SelObjBr);
                            DeleteObject(Brush);
                          end;
                      end;
                    Result := 1;
                  end;

      WM_DESTROY: begin
                    PostQuitMessage(0);
                    Exit;
                  end;
    else
      Result := DefWindowProc(Window, Message, wParam, lParam);
    end;
end;

begin
  with WindowClass do
    begin
      lpszClassName := WindowName;
      lpfnWndProc := @WindowProc;
      cbClsExtra := 0;
      cbWndExtra := 0;
      hInstance := 0;
      lpszMenuName := nil;
      hIcon := LoadIcon(0, IDI_APPLICATION);
      hCursor := LoadCursor(0, IDC_ARROW);
      hbrBackground := GetStockObject(WHITE_BRUSH);
    end;

  if RegisterClass(WindowClass) = 0 then Exit;

  hWindow := CreateWindow(WindowName, WindowName, WS_OVERLAPPEDWINDOW, (GetSystemMetrics(SM_CXSCREEN) - 500) div 2, (GetSystemMetrics(SM_CYSCREEN) - 300) div 2, 500, 300, 0, 0, HInstance, nil);

  ShowWindow(hWindow, SW_SHOWNORMAL);
  UpdateWindow(hWindow);

  while GetMessage(AMessage, 0, 0, 0) do
    begin
      TranslateMessage(AMessage);
      DispatchMessage(AMessage);
    end;
end.


Можно просто скопировать его в Delphi и компилировать.. Можно конечно обрабатывать WM_LBUTTONDOWN/WM_LBUTTONUP кнопки, но это же только с мышкой, а на кнопку же можно еще нажать и с помощью клавиатуры.. Лучше всего было бы обрабатывать нажатие, чтобы перерисовывать ее в WM_DRAWITEM мне так кажется.. Помогите пожалуста, может кто-то уже делал что я хочу, чтобы не придумывать велосипед..
PM MAIL   Вверх
ama_kid
Дата 12.3.2007, 14:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


АСУТП-кодер
***


Профиль
Группа: Комодератор
Сообщений: 1460
Регистрация: 5.3.2007
Где: Москва

Репутация: 19
Всего: 95



Во-первых, будь внимательней:
    old_proc := Pointer(GetWindowLong(hTestBtn, GWL_WNDPROC));

Во, вторых: при нажатии на кнопку главному окну приходит сообщение WM_COMMAND:
Код

      WM_COMMAND: begin
                  if (LO(wParam)=ID_TestBtn) and (HI(wParam)=BN_CLICKED) then ShowMessage('Yoo');
                 end;



--------------------
самурай без меча подобен самураю с мечом, но только без меча 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

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

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0747 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.