Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Помогите разобраться с простейшей программой на API


demon ©   (2008-08-17 17:40:00) 

Вот, написал для примера исходник http://njg.890m.com/listbox.zip
Никак не могу сделать чтобы листбокс не мерцал приперерысовке.
В чем может быть дело?


DVM   (2008-09-01 16:54:00) [1]


> может в исходнике bred2 чего отрою.

bred2 тот еще образец для подражания.


DVM   (2008-09-01 16:46:00) [2]


> Это осталось от экспериментов, забыл удалить.

Ты сначала исправь все такие места.


demon   (2008-09-01 16:24:00) [3]

ясно. Это осталось от экспериментов, забыл удалить.
Ладно, раз идей нету, попробую сам разобраться, может в исходнике bred2 чего отрою.


DVM   (2008-09-01 10:51:00) [4]


> demon ©   (01.09.08 00:35) [8]
>
> А поподробнее?

Посмотрел я твой код. У меня он правда работает нормально вроде, но недостатки там есть, в том числе и связанные возможно с прорисовкой неверной.

Запомни, если ты вставил в оконную процедуру окна обработку какого-либо сообщения, то ты обязан вернуть результат обработки. Для некоторых сообщений это не критично, для других чревато сбоями. Так положено. Вот, например, фрагмент твоего кода:

     WM_CTLCOLORLISTBOX:
       begin

       end;


Пустой обработчик. А в MSDN тем временем сказано, что:

Return Values
If an application processes this message, it must return the handle of a brush. Windows uses the brush to paint the background of the list box.

И это не единственное такое место в твоем коде. Раз взялся за WinAPI - будь добр играть по его правилам.


demon   (2008-09-01 02:56:00) [5]

Хотел промолчать...
Но как меня дастала тупость приколов некоторых пользователей! А от вас Герман я вообще пользы никакой не получил, зато ведете себя как будто админ внештатный.
Пользуясь случаем, спасибо DVM, Юрий Зотовза все.


Германн   (2008-09-01 01:12:00) [6]


> demon ©   (01.09.08 00:35) [8]
>
> А поподробнее?
> ...я перезалил исправлений код по ссылке в первом сообщении
> (точнее в нулевом )
>

Ну если "перезалил", то теперь "переотливай".


demon   (2008-09-01 00:35:00) [7]

А поподробнее?
...я перезалил исправлений код по ссылке в первом сообщении (точнее в нулевом )


DVM   (2008-08-31 23:19:00) [8]


> Как исправить?

объекты освобождать надо


demon   (2008-08-31 23:09:00) [9]

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

Как исправить?


Германн   (2008-08-18 00:52:00) [10]


> DVM ©   (17.08.08 23:13) [3]
>
> Если опустить прочие недостатки

Хм. Оригинальная формулировка. :)


demon   (2008-08-18 00:45:00) [11]

Да, утечка хэндлов на лицо, устраню.
Спасибо, DVM, счас буду искать отличия :)


DVM   (2008-08-17 23:13:00) [12]

Если опустить прочие недостатки кода из [0], то вот немерцающий вариант:


program listbox_api;

uses
 Windows, Messages, Types;

const
 WndClass   = 'TWinApiWnd';
 WndCaption = 'Ðàáîòà ñ ListBox';
 ListBoxID  = 1;

var
 Wc: TWndClassEx;
 Wnd: HWND;
 Msg: TMsg;
 ListBox: THandle;
 ListDC : hDC;
 RectLB : TRect;
 TextLB : array [0..$400] of Char;
 Client:TRect;
 ListLineHeight: integer;
 OldLBProc: pointer;

function WindowProc( Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM ): LRESULT; stdcall;
begin
  case Msg of
     WM_DESTROY:
       begin
        PostQuitMessage( 0 );
        Result := 0;
        Exit;
       end;
     WM_SIZE : MoveWindow(ListBox, 10, 10, LOWORD(lparam)-20, HIWORD(lparam)-20, true);
     WM_CTLCOLORLISTBOX:
       begin

       end;
     WM_MEASUREITEM :
     case wParam of
       ListBoxID :
         begin
           with PMEASUREITEMSTRUCT(lParam)^ do
             begin
               itemHeight := 14;
             end;
         end;
     end;

    WM_DRAWITEM :
     case wParam of
       ListBoxID :
         begin
           RectLB  := PDRAWITEMSTRUCT(lParam).rcItem;
           ListDC  := PDRAWITEMSTRUCT(lParam).hDC;

           if (Integer(PDRAWITEMSTRUCT(lParam).ItemID) > - 1) then
             begin
               if ((PDRAWITEMSTRUCT(lParam).itemState and ODS_SELECTED) 0) then
                 begin   // Âûäåëåíûé àéòýì
                   FillRect(ListDC, RectLB, CreateSolidBrush($990000) );
                   SetBkColor(ListDC, RGB(0,0,128) );
                   SetTextColor(ListDC, RGB(255,255,255) );
                 end
               else
                 begin   // Íå âûäåëåíûé àéòýì
                   FillRect(ListDC, RectLB, CreateSolidBrush($000000) );
                   SetBkColor(ListDC,  RGB(0,0,0) );
                   SetTextColor(ListDC,RGB(0,255,0) );
                 end;
               // ïåðåðûñîâûâàå&# 236; òåêñò
               SendMessage(ListBox, LB_GETTEXT, PDRAWITEMSTRUCT(lParam).ItemID, LongInt(@TextLB[0]));
               DrawText(ListDC, @TextLB[0], - 1, RectLB, DT_SINGLELINE or DT_VCENTER);
             end;

             GetClientRect(ListBox,Client);
             ListLineHeight:= PDRAWITEMSTRUCT(lParam).rcItem.Bottom - PDRAWITEMSTRUCT(lParam).rcItem.top;
             client.Top:= client.Top+ListLineHeight*4;
             FillRect(ListDC,Client,CreateSolidBrush($000000));     // öâåò îñòàòêà ëèñòà áåç àéòýìîâ

           if ((PDRAWITEMSTRUCT(lParam).itemState and ODS_FOCUS) 0) then DrawFocusRect(ListDC, PDRAWITEMSTRUCT(lParam).rcItem);
         end;
     end;
     else
       Result := DefWindowProc( Wnd, Msg, wParam, lParam );
  end;
end;

function LBProc(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
 case Msg of
   WM_ERASEBKGND:
     begin
       result :=0;
     end;
 else
   Result := CallWindowProc(OldLBProc, ListBox, Msg, wParam, lParam);
 end;
end;

begin
 with Wc do     // ñîçäà¸ì êëàññ îêíà
  begin
     cbSize := SizeOf( Wc );
     style := CS_HREDRAW or CS_VREDRAW;
     lpfnWndProc := @WindowProc;
     cbClsExtra := 0;
     cbWndExtra := 0;
     hInstance := hInstance;
     hIcon := LoadIcon( 0, IDI_APPLICATION );
     hCursor := LoadCursor( 0, IDC_ARROW );
     hbrBackground := CreateSolidBrush($004499);
     lpszMenuName := nil;
     lpszClassName := WndClass;
  end;

  RegisterClassEx( Wc );    // ðåãèñòðèðóåì êëàññ îêíà

  Wnd := CreateWindowEx(    // Ñîçäà¸ì îêíî
  0, WndClass,
  WndCaption,
  WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN,
  400, 200, 300, 300,
  0, 0, hInstance, nil );

  ListBox := CreateWindowEx(   // Ñîçäà¸ì ListBox
   0, 'Listbox', '',
   WS_CHILD or WS_VISIBLE or LBS_OWNERDRAWFIXED or LBS_HASSTRINGS,
   10, 10, 270, 250, Wnd,
   ListBoxID, hInstance,
   nil );

  OldLBProc:=Pointer(SetWindowLong(ListBox, GWL_WNDPROC, longint(@LBProc)));

  // ×òî-òî ñî øðèôòîì...
  SendMessage( ListBox, WM_SETFONT, GetStockObject( ANSI_VAR_FONT ), 1 );

  // Äîáàâëÿåì 4 ñòðîêè äëÿ ïðèìåðà
  SendMessage( ListBox, LB_ADDSTRING, 0, LongInt(pchar('Ñòðî÷êà 1')));
  SendMessage( ListBox, LB_ADDSTRING, 0, LongInt(pchar('Ñòðî÷êà 2')));
  SendMessage( ListBox, LB_ADDSTRING, 0, LongInt(pchar('Ñòðî÷êà 3')));
  SendMessage( ListBox, LB_ADDSTRING, 0, LongInt(pchar('Ñòðî÷êà 4')));

  // Ïîêàçûâàåì ãëàâíîå îêíî
  ShowWindow( Wnd, SW_SHOWNORMAL );

  while GetMessage( Msg, 0, 0, 0 ) do
  begin
     TranslateMessage( Msg );
     DispatchMessage( Msg );
  end;
  Halt( Msg.wParam );
end.


DVM   (2008-08-17 22:53:00) [13]


> demon ©   (17.08.08 17:40)  

и еще не стирать и не рисовать фон, если ты все равно сверху нарисуешь прямоугольник.

А вообще код в WM_DRAWITEM ужасен, например вот это:

FillRect(ListDC, RectLB, CreateSolidBrush($000000) );


Правильный$Вася   (2008-08-17 22:30:00) [14]

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


Наверх

Титульная страница Поиск, карта сайта Написать письмо