www.adept7.kiev.ua
| Форум| Гостевая| Ссылки| Программы| Исходные тексты| Наши партнеры|
   
| Главная| Рассылки| Услуги| Библиотека| Новости| Авторам| Программистам| Студентам|
delphi c++ assembler
 
GDI и Графический интрефейс
Копирование экрана
Быстрая отрисовка BitMap в компоненте TListBox
Изменение цвета строк компонента TGrid в режиме run-time в зависимости от данных в текущей записи нaбора данных.
Проверка ситуации "выход за границы списка" при нажатии правой кнопки на списке TListBox
Как рисовать прямо на экране?
Как быстро выводить графику? (А то Canvas очень медленно работает)
Способ быстрой очистки canvasа .
Использование InvalidateRect()t для перерисовки всей формы.
Отключение обновления окна
Как перехватить нажатие кнопки PrintScreen в Windows.
Обновление Рабочего Стола Windows.
MDI - родительское окно с фоновым рисунком.
Отключение перерисовки содержимого окна при перемещении
Обои рабочего стола
Как создать иконку из bitmap'а.
Преобразование цвета в оттенки серого.
Как вывести на Canvas надпись под углом?
Как вывести графику на принтер?
Как подгрузить 256 цветный битмап из ресурса и отобразить его в нормальной палитре?
Как поместить двумерный массив в Image.
Работа с палитрой.
Заполнить Canvas рисунком с рабочего стола.
Как вставить изображение в компонент TListBox
Как из Делфи рисовать в любой части экрана или в чужом окне.
Написание текста под углом.
Преобразование цвета RGB 34 HLS (яркость, насыщенность, оттенок).
Как узнать число цветов у данного компьютера.
Как скопировать экран.
Как нарисовать "неактивный"(disable) текст.
Как менять разрешение экрана по ходу выполнения программы.
Как поместить картинку из базы данных в компонент TIMAGES.
Как извлеч из EXE-файла иконки и рисовать ее в TImages.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


Как работать с палитрой в Delphi? На форме установлен TImage и видна картинка (*.BMP файл), как изменить у него палитру цветов ?
Палитра в TBitmap и TMetaFile доступна через property Palette. Если палитра имеется (что совсем необязательно), то Palette<>0:
procedure TMain.BitBtnClick(Sender: TObject);
var
  Palette : HPalette;
  PaletteSize : Integer;
  LogSize: Integer;
  LogPalette: PLogPalette;
  Red : Byte;
begin
  Palette :=Image.Picture.Bitmap.ReleasePalette;
  // здесь можно использовать просто Image.Picture.Bitmap.Palette, но  я не
  // знаю, удаляются ли ненужные палитры автоматически
  if Palette=0 then exit; //Палитра отсутствует
  PaletteSize :=0;
  if GetObject(Palette, SizeOf(PaletteSize), @PaletteSize)=0 then Exit;
  // Количество элементов в палитре=paletteSize
  if PaletteSize=0 then Exit; // палитра пустая
  // определение размера палитры
  LogSize :=SizeOf(TLogPalette) + (PaletteSize - 1) * SizeOf(TPaletteEntry);
  GetMem(LogPalette, LogSize);
  try
    // заполнение полей логической палитры
    with LogPalette^ do begin
      palVersion :=$0300;    palNumEntries :=PaletteSize;
      GetPaletteEntries(Palette, 0, PaletteSize, palPalEntry);
      // делаете что нужно с палитрой, например:
      Red :=palPalEntry[PaletteSize-1].peRed;
      Edit1.Text :='Красная составляющего последнего элемента  палитры='+IntToStr(Red);
      palPalEntry[PaletteSize-1].peRed := 0;
      //.......................................
    end;
    // завершение работы
    Image.Picture.Bitmap.Palette :=CreatePalette(LogPalette^);
  finally
    FreeMem(LogPalette, LogSize);
    // я должен позаботиться сам об удалении Released Palette
    DeleteObject(Palette);
  end;
end;

{ Этот модуль заполняет фон формы рисунком bor6.bmp (256 цветов)
  и меняет его палитру при нажатии кнопки }
unit bmpformu;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type
  TBmpForm=class(TForm)
    Button1: TButton;
    procedure FormDestroy(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    Bitmap: TBitmap;
    procedure ScrambleBitmap;
    procedure WMEraseBkgnd(var m: TWMEraseBkgnd); message WM_ERASEBKGND;
end;
var
  BmpForm: TBmpForm;
implementation
{$R *.DFM}
procedure TBmpForm.FormCreate(Sender: TObject);
begin
  Bitmap :=TBitmap.Create;
  Bitmap.LoadFromFile('bor6.bmp');
end;
procedure TBmpForm.FormDestroy(Sender: TObject);
begin
  Bitmap.Free;
end;
// since we're going to be painting the whole form, handling this
// message will suppress the uneccessary repainting of the background
// which can result in flicker.
procedure TBmpform.WMEraseBkgnd(var m : TWMEraseBkgnd);
begin
  m.Result :=LRESULT(False);
end;
procedure TBmpForm.FormPaint(Sender: TObject);
var x, y: Integer;
begin
  y :=0;
  while y < Height do begin
    x :=0;
    while x < Width do begin
      Canvas.Draw(x, y, Bitmap);
      x :=x + Bitmap.Width;
    end;
    y :=y + Bitmap.Height;
  end;
end;
procedure TBmpForm.Button1Click(Sender: TObject);
begin
  ScrambleBitmap; Invalidate;
end;
// scrambling the bitmap is easy when it's has 256 colors:
// we just need to change each of the color in the palette
// to some other value.
procedure TBmpForm.ScrambleBitmap;
var
  pal: PLogPalette;
  hpal: HPALETTE;
  i: Integer;
begin
  pal :=nil;
  try
    GetMem(pal, sizeof(TLogPalette) + sizeof(TPaletteEntry) * 255);
    pal.palVersion :=$300;
    pal.palNumEntries :=256;
    for i :=0 to 255 do
    begin
      pal.palPalEntry[i].peRed :=Random(255);
      pal.palPalEntry[i].peGreen :=Random(255);
      pal.palPalEntry[i].peBlue :=Random(255);
    end;
    hpal :=CreatePalette(pal^);
    if hpal <> 0 then
      Bitmap.Palette :=hpal;
  finally
    FreeMem(pal);
  end;
end;
end.


Заполняет Canvas рисунком с рабочего стола, учитывая координаты. Function PaintDesktop(HDC) : boolean;
Например: PaintDesktop(form1.Canvas.Handle); 
Как вставить растровое изображение в компонент ListBox?
Для этого необходимо установить в инспекторе объектов поле Style в lbOwnerDrawFixed, при фиксированной высоте строки, или в lbOwnerDrawVariable, при переменной, и установить собственный обработчик события для OnDrawItem. В этом обработчике и надо рисовать растровое изображение.
    Пример:
    Рисуются изображения размером 32*16 (размер стандартного глифа для Delphi). Очень полезно при поиске нужного изображения для кнопок!
    Установить в инспекторе объектов для ListBox поле ItemHeight=19, а поле Color=clBtnFace.
    { Загрузить список файлов в ListBox1 при нажатии на кнопку Load (например)}
    procedure TForm1.bLoadClick(Sender: TObject);
    i S : String; 
    begin 
      ListBox1.Clear; {чистим список}
      S :='*.bmp'#0; {задаем шаблон}
      ListBox1.Perform(LB_DIR, DDL_ReadWrite, Longint(@S[1])); {заполняем список} 
    end; 
              ............ 
    {Отобразить изображения и имена файлов в ListBox}
    procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; 
              Rect: TRect; State: DrawState); 
    VAR 
      Bitmap : TBitmap;
      Offset : Integer; 
      BMPRect: TRect; 
    begin 
      WITH (Control AS TListBox).Canvas DO BEGIN 
        FillRect(Rect); 
        Bitmap :=TBitmap.Create;
        Bitmap.LoadFromFile(ListBox1.Items[Index]); 
        Offset :=0; 
        IF Bitmap <> NIL THEN BEGIN 
          BMPRect :=Bounds(Rect.Left+2, Rect.Top+2, 
                            (Rect.Bottom-Rect.Top-2)*2, Rect.Bottom-Rect.Top-2); 
          {StretchDraw(BMPRect, Bitmap); Можно просто нарисовать, но лучше сначала убрать фон} 
          BrushCopy(BMPRect,Bitmap, Bounds(0, 0, Bitmap.Width, Bitmap.Height),
                    Bitmap.Canvas.Pixels[0, Bitmap.Height-1]); 
          Offset :=(Rect.Bottom-Rect.Top+1)*2; 
        END; 
        TextOut(Rect.Left+Offset, Rect.Top, ListBox1.Items[Index]); 
        Bitmap.Free; 
      END; 
    end;
    Данный пример работает медленно, но оптимизация, для ускорения, вызвала бы трудность в понимании общего принципа его работы.

    Можно ли из Delphi рисовать в любой части экрана или в чужом окне?
    Для этого надо воспользоваться функциями API. Получить контекст чужого окна, либо всего экрана:
    function GetDC(Wnd: HWnd): HDC;
    где Wnd - указатель на нужное окно, или 0 для получения контекста всего экрана.
    И далее, пользуясь функциями API, нарисовать все что надо.
    Пример:
    PROCEDURE DrawOnScreen; 
    i ScreenDC: hDC; 
    BEGIN 
      ScreenDC :=GetDC(0); {получить контекст экрана} 
      Ellipse(ScreenDC, 0, 0, 200, 200); {нарисовать} 
      ReleaseDC(0,ScreenDC); {освободить контекст} 
    END;
    Не забывайте после своих манипуляций посылать пострадавшим (или всем) окнам сообщение о необходимости перерисовки, для восстановления их первоначального вида.


     
     

    Написание текста под углом


    { Эта процедура устанавливает угол вывода текста для указанного Canvas, угол в градусах }
    { Шрифт должен быть TrueType ! }
    procedure CanvasSetTextAngle(c: TCanvas; d: single);
    var  LogRec: TLOGFONT;    { Информация о шрифте }
    begin
     {Читаем текущюю инф. о шрифте }
     GetObject(c.Font.Handle,SizeOf(LogRec) ,Addr(LogRec) );
     { Изменяем угол }
     LogRec.lfEscapement :=round(d*10);
     { Устанавливаем новые параметры }
     c.Font.Handle :=CreateFontIndirect(LogRec);
    end;

    Преобразование цвета RGBуHLS


    { Максимальные значения }
    Const
     HLSMAX=240;
     RGBMAX=255;
     UNDEFINED=(HLSMAX*2) div 3;
    i
     H, L, S  : integer; { H-оттенок, L-яркость, S-насыщенность }
     R, G, B  : integer; { цвета }
    procedure RGBtoHLS;
    i
     cMax,cMin  : integer;
     Rdelta,Gdelta,Bdelta : single;
    Begin
      cMax :=max( max(R,G), B);
      cMin :=min( min(R,G), B);
      L :=round( ( ((cMax+cMin)*HLSMAX) + RGBMAX )/(2*RGBMAX) );
      if (cMax=cMin) then begin
          S :=0; H :=UNDEFINED;
      end else begin
          if (L <=(HLSMAX/2)) then
            S :=round( ( ((cMax-cMin)*HLSMAX) + ((cMax+cMin)/2) ) / (cMax+cMin) )
          else
            S :=round( ( ((cMax-cMin)*HLSMAX) + ((2*RGBMAX-cMax-cMin)/2) )
                / (2*RGBMAX-cMax-cMin) );
          Rdelta :=( ((cMax-R)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin);
          Gdelta :=( ((cMax-G)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin);
          Bdelta :=( ((cMax-B)*(HLSMAX/6)) + ((cMax-cMin)/2) ) / (cMax-cMin);
          if (R=cMax) then H :=round(Bdelta - Gdelta)
          else if (G=cMax) then H :=round( (HLSMAX/3) + Rdelta - Bdelta)
          else H :=round( ((2*HLSMAX)/3) + Gdelta - Rdelta );
          if (H < 0) then H:=H + HLSMAX;
          if (H> HLSMAX) then H:=H - HLSMAX;
      end;
      if S<0 then S:=0; if S>HLSMAX then S:=HLSMAX;
      if L<0 then L:=0; if L>HLSMAX then L:=HLSMAX;
    end;
    procedure HLStoRGB;
    i
     Magic1,Magic2 : single;
      function HueToRGB(n1,n2,hue : single) : single;
      begin
        if (hue < 0) then hue :=hue+HLSMAX;
        if (hue> HLSMAX) then hue:=hue -HLSMAX;
        if (hue < (HLSMAX/6)) then
            result:=( n1 + (((n2-n1)*hue+(HLSMAX/12))/(HLSMAX/6)) )
        else
        if (hue < (HLSMAX/2)) then result:=n2 else
        if (hue < ((HLSMAX*2)/3)) then
            result:=( n1 + (((n2-n1)*(((HLSMAX*2)/3)-hue)+(HLSMAX/12))/(HLSMAX/6)))
        else result:=( n1 );
      end;
    begin
      if (S=0) then begin
          B:=round( (L*RGBMAX)/HLSMAX ); R:=B; G:=B;
      end else begin
          if (L <=(HLSMAX/2)) then Magic2 :=(L*(HLSMAX + S) + (HLSMAX/2))/HLSMAX
          else Magic2 :=L + S - ((L*S) + (HLSMAX/2))/HLSMAX;
          Magic1 :=2*L-Magic2;
          R :=round( (HueToRGB(Magic1,Magic2,H+(HLSMAX/3))*RGBMAX + (HLSMAX/2))/HLSMAX );
          G :=round( (HueToRGB(Magic1,Magic2,H)*RGBMAX + (HLSMAX/2)) / HLSMAX );
          B :=round( (HueToRGB(Magic1,Magic2,H-(HLSMAX/3))*RGBMAX + (HLSMAX/2))/HLSMAX );
      end;
      if R<0 then R:=0; if R>RGBMAX then R:=RGBMAX;
      if G<0 then G:=0; if G>RGBMAX then G:=RGBMAX;
      if B<0 then B:=0; if B>RGBMAX then B:=RGBMAX;
    end;

    Число цветов (цветовая палитра) у данного компьютера
    Эта функция возвращает число бит на точку у данного компьютера. Так, например, 8 - 256 цветов, 4 - 16 цветов ...
    function GetDisplayColors : integer;
    i tHDC  : hdc;
    begin
     tHDC:=GetDC(0);
     result:=GetDeviceCaps(tHDC, 12)* GetDeviceCaps(tHDC, 14);
     ReleaseDC(0, tHDC);
    end;

    Копирование экрана


    unit ScrnCap;
    interface
    uses WinTypes, WinProcs, Forms, Classes, Graphics, Controls;
     { Копирует прямоугольную область экрана }
    function CaptureScreenRect(ARect : TRect) : TBitmap;
     { Копирование всего экрана }
    function CaptureScreen : TBitmap;
     { Копирование клиентской области формы или элемента }
    function CaptureClientImage(Control : TControl) : TBitmap;
     { Копирование всей формы элемента }
    function CaptureControlImage(Control : TControl) : TBitmap;
    {===============================================================}
    implementation
    function GetSystemPalette : HPalette;
    i
     PaletteSize  : integer;
     LogSize      : integer;
     LogPalette  : PLogPalette;
     DC          : HDC;
     Focus        : HWND;
    begin
     result:=0;
     Focus:=GetFocus;
     DC:=GetDC(Focus);
     try
      PaletteSize:=GetDeviceCaps(DC, SIZEPALETTE);
      LogSize:=SizeOf(TLogPalette)+(PaletteSize-1)*SizeOf(TPaletteEntry);
      GetMem(LogPalette, LogSize);
      try
        with LogPalette^ do
        begin
          palVersion:=$0300;
          palNumEntries:=PaletteSize;
          GetSystemPaletteEntries(DC, 0, PaletteSize, palPalEntry);
        end;
        result:=CreatePalette(LogPalette^);
      finally
        FreeMem(LogPalette, LogSize);
      end;
     finally
      ReleaseDC(Focus, DC);
     end;
    end;
    function CaptureScreenRect(ARect : TRect) : TBitmap;
    i
     ScreenDC : HDC;
    begin
     Result:=TBitmap.Create;
     with result, ARect do begin
      Width:=Right-Left;
      Height:=Bottom-Top;
      ScreenDC:=GetDC(0);
      try
        BitBlt(Canvas.Handle, 0,0,Width,Height,ScreenDC, Left, Top, SRCCOPY );
      finally
        ReleaseDC(0, ScreenDC);
      end;
      Palette:=GetSystemPalette;
     end;
    end;
    function CaptureScreen : TBitmap;
    begin
     with Screen do
      Result:=CaptureScreenRect(Rect(0,0,Width,Height));
    end;
    function CaptureClientImage(Control : TControl) : TBitmap;
    begin
     with Control, Control.ClientOrigin do
      result:=CaptureScreenRect(Bounds(X,Y,ClientWidth,ClientHeight));
    end;
    function CaptureControlImage(Control : TControl) : TBitmap;
    begin
     with Control do
      if Parent=Nil then
        result:=CaptureScreenRect(Bounds(Left,Top,Width,Height))
      else
      with Parent.ClientToScreen(Point(Left, Top)) do
        result:=CaptureScreenRect(Bounds(X,Y,Width,Height));
    end;
    end.

    Draw disable text


    {************************ Draw Disabled Text **************
     ***** This function draws text in "disabled" style.  *****
     ***** i.e. the text is grayed .                      *****
     **********************************************************}
    function DrawDisabledText (Canvas : tCanvas; Str: PChar; Count: Integer;
                              i Rect: TRect;  Format: Word): Integer;
    begin
      SetBkMode(Canvas.Handle, TRANSPARENT);
      OffsetRect(Rect, 1, 1);
      Canvas.Font.color:=ClbtnHighlight;
      DrawText (Canvas.Handle, Str, Count, Rect,Format);
      Canvas.Font.Color:=ClbtnShadow;
      OffsetRect(Rect, -1, -1);
      DrawText (Canvas.Handle, Str, Count, Rect, Format);
    end;

    Как менять разрешение экрана по ходу выполнения программы


    function SetFullscreenMode:Boolean;
    i DeviceMode : TDevMode;
    begin
     with DeviceMode do begin
      dmSize:=SizeOf(DeviceMode);
      dmBitsPerPel:=16;
      dmPelsWidth:=640;
      dmPelsHeight:=480;
      dmFields:=DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
      result:=False;
      if ChangeDisplaySettings(DeviceMode,CDS_TEST or CDS_FULLSCREEN) <> DISP_CHANGE_SUCCESSFUL 
      then Exit;
      Result:=ChangeDisplaySettings(DeviceMode,CDS_FULLSCREEN)=DISP_CHANGE_SUCCESSFUL;
     end;
    end;
    procedure RestoreDefaultMode;
    i T : TDevMode absolute 0;
    begin
     ChangeDisplaySettings(T,CDS_FULLSCREEN);
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
     if setFullScreenMode then begin
      sleep(7000);
      RestoreDefaultMode;
     end;
    end;

    Как поместить картинку из базы данных, например MsSQL, в компонент TIMAGE ?


    1) Предполагается, что поле BLOB (например, Pict)
    2) в запросе Query.SQL пишется что-то вроде
    'select Pict from sometable where somefield=somevalue'
    3) запрос открывается
    4) делается "присваивание":
    Image1.Picture.Assing(TBlobField(Query.FieldByName('Pict'))
    или, если известно, что эта картинка - Bitmap, то можно
    Image1.Picture.Bitmap.Assing(TBlobField(Query.FieldByName('Pict'))

    А можно воспользоваться компонентом TDBImage.


    Извлечение иконки из Exe - файла и рисование ее в TImages.


    Каким образом извлечь иконку из EXE- и DLL-файлов (ExtractAssociatedIcon) и отобразить ее на компоненте Timage или небольшой области на форме?

    --------------------------------------------------------------------------------

    uses ShellApi;

    procedure TForm1.Button1Click(Sender: TObject);

    var IconIndex : word; h : hIcon;

    begin IconIndex :=0; h :=ExtractAssociatedIcon(hInstance, 'C:\WINDOWS\NOTEPAD.EXE', IconINdex); DrawIcon(Form1.Canvas.Handle, 10, 10, h);

    end;


1.Копирование экрана
Для копирования изображения, находящегося в клиентской части формы есть метод GetFormImage. Для копирования любого прямоугольника экрана можно воспользоваться функциями GDI.
// Копирование произвольной прямоугольной области экрана
Function CaptureScreenRect( ARect: TRect ): TBitmap;
i
  ScreenDC: HDC;
begin
  Result :=TBitmap.Create;
  with Result, ARect do
  begin
    Width :=Right - Left;
    Height :=Bottom - Top;
    // получаем для экрана контекст устройства
    ScreenDC :=GetDC( 0 );
    try
      // копируем оттуда прямоугольную область на канву
      // растрового изображения
      BitBlt( Canvas.Handle, 0, 0, Width, Height, ScreenDC,
        Left, Top, SRCCOPY );
    finally
      ReleaseDC( 0, ScreenDC );
    end;
  end;
end;
Таким образом, задавая нужный прямоугольник, можно получить изображение любой части экрана, получить изображение любого элемента формы(кнопок , выпадающих списков и так далее).
Пример для копирования нужного элемента формы или всей формы, включая и заголовок и рамку:
Function CaptureControlImage( Control: TControl ): TBitmap;
begin
  with Control do
    IF Parent=nil
        Then Result :=CaptureScreenRect( Bounds( Left, Top, Width,Height ))
    Else With Parent.ClientToScreen( Point( Left, Top )) DO
                        Result :=CaptureScreenRect( Bounds( X, Y, Width,Height ));
end;
Вернуться к содержанию


2.Быстрая отрисовка BitMap в компоненте TListBox
Эту задачу можно решить разными способами, но в случае, когда изображение в списке должно меняться в зависимости от каких-то условий в режиме run-time, то встает вопрос о скорости перерисовки при скроллировании списка.
Вот одно из возможных решений: создается компонент TImageList, который содержит весь необходимый набор изображений. И на событие TListBox.onDrawItem непосредственно на канве списка рисуется нужный BitMap самим TImageList.
Метод TImageList.Draw работает очень быстро, так что при скролировании списка в несколько сотен записей замедление не заметно.
Примечание: В данном примере IMAGE_NORMAL, IMAGE_MESSAGE и IMAGE_AUTOANS константы, определяющие какое именно изображение надо рисовать в зависимости от значения функции (собственной) GetUserStatus.
//------------------------------------------------------------------------------
Procedure TMain.UserListDrawItem(Control: TWinControl; Index: Integer;
                                Rect: TRect; State: TOwnerDrawState);
Begin
  With TCustomListBox(Control)  Do
  Begin
    Canvas.FillRect(Rect);
        // Вывод самого текста текущего Item-а списка со сдвигом, чтобы освободить
        // место для изображения
    Canvas.TextOut(Rect.Left + 2 + ImageList.Height, Rect.Top+3, Items[Index]);
    Rect.Bottom:=Rect.Top  + ImageList.Height; // перерисовывать только
    Rect.Right :=Rect.Left + ImageList.Width;  // часть , на которой картинка
    Rect.Top:=Rect.Top+2;
    // по состоянию юзера перерисовывается изображение
    Case  GetUserStatus(Index) Of
            suNormal  : ImageList.Draw(Canvas,Rect.Left,Rect.Top,IMAGE_NORMAL);
            suMessage : ImageList.Draw(Canvas,Rect.Left,Rect.Top,IMAGE_MESSAGE);
            suAutoans : ImageList.Draw(Canvas,Rect.Left,Rect.Top,IMAGE_AUTOANS);
    End; // Case
  End; // With
End;
//------------------------------------------------------------------------------

3.Изменение цвета строк компонента TGrid в режиме run-time в зависимости от данных в текущей записи нaбора данных.
Примечание: В данном примере SF_TYPE - внутренняя константа, ValueDesigner - переменная типа RECORD, содержащая нужные цвета.
Обрабатывается событие TGrid.onDrawColumnCell:
//------------------------------------------------------------------------------
Procedure TMainForm.GridBookDrawColumnCell(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn;
  State: TGridDrawState);
Begin
        // Изменение цвета фонта записи
    IF TDBGrid(Sender).DataSource.DataSet.FieldByName('OWNER_TYPE').AsInteger=SF_TYPE
    Then TDBGrid(Sender).Canvas.Font.Color:=ValueDesigner.colorSimpleSF
    Else TDBGrid(Sender).Canvas.Font.Color:=ValueDesigner.colorChildrenSF;
    // Поправка для выделенной записи , иначе текст не будет автоматически подсвечен           
    IF (gdSelected in State) AND TDBGrid(Sender).Focused
    Then TDBGrid(Sender).Canvas.Font.Color:=clHighLightText;
    TDBGrid(Sender).DefaultDrawColumnCell(Rect,DataCol,Column,State);
    // установка знака АКЦЕПТОВАНО в поле Sign
    IF CompareText(Field.FieldName,'SIGN')=0
    Then IF NOT TDBGrid(Sender).DataSource.DataSet.FieldByName('ACCEPT').IsNull
          Then TDBGrid(Sender).Canvas.Draw(Rect.Left,Rect.Top,
                                        AcceptBMP.Picture.Bitmap)
end;
//------------------------------------------------------------------------------
Вернуться к содержанию


4.Проверка ситуации "выход за границы списка" при нажатии правой кнопки на списке TListBox
При нажатии правой кнопки на компоненте TListBox вызывается PopUpMenu, но все пункты этого меню должны быть применены к тому элементу в списке, на котором и была нажата кнопка. Этот элемент может не быть в данный момент текущим ( то есть выделенным) и вообще, правая кнопка может быть нажата на той части компоненты, где реальный список уже закончился. Данная задача может быть решена следующим образом:
Обрабатывается событие TListBox.onMouseDown
//------------------------------------------------------------------------------
procedure TMain.UserListMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
i Point : TPoint;
    I    : Integer;
Const NoHit=-1;
begin
    If Button=mbRight
    Then Begin
              // Если нажата правая кнопка мыши, выяснить, не попал ли курсор
              // на элемент списка UserList
              Point.X:=x;
              Point.Y:=y;
              I:=UserList.ItemAtPos(Point , True);
              If Not(i=NoHit) Then
                Begin
                    // курсор попал на элемент списка с номером i
                    // принудительно назначаем его текущим, т.е. отмеченным
   
                    UserList.ItemIndex:=I;
                    TListBox(Sender).PopUpMenu.AutoPopup:=True;
                  End
              Else // курсор промахнулся , нет смысла активизировать меню
                  TListBox(Sender).PopUpMenu.AutoPopup:=False;
          End;
end;
//------------------------------------------------------------------------------
Вернуться к содержанию

Как рисовать прямо на экране?
  ........................................................
  Procedure DrawOnScreen;
  i DC:HDC;
      DesktopCanvas:TCanvas;
  begin
    DC:=GetDC(0);  // получили DC экрана
    try
      DesktopCanvas:=TCanvas.Create;
      DesktopCanvas.Handle:=DC;
      ..................
      // здесь рисуем на Canvas экрана
      ..................
    finally
      ReleaseDC(0,DC);
      DesktopCanvas.Free;
    end;
  end;
  ........................................................
Вернуться к содержанию

Как быстро выводить графику? (А то Canvas очень медленно работает).
  Вот пример заполнения формами точками случайного цвета.
  ........................................................
  type
    TRGB=record
      b,g,r:byte;
    end;
    ARGB=array [0..1] of TRGB;
    PARGB=^ARGB;

  i
    b:TBitMap;

  procedure TForm1.FormCreate(sender:TObject);
  begin
    b:=TBitMap.Create;
    b.pixelformat:=pf24bit;
    b.width:=Clientwidth;
    b.height:=Clientheight;
  end;

  procedure TForm1.Tim1OnTimer(sender:TObject);
  i
    p:PARGB;
    x,y:integer;
  begin
    for y:=0 to b.height-1 do
    begin
      p:=b.scanline[y];
      for x:=0 to b.width-1 do
      begin
        p[x].r:=random(256);
        p[x].g:=random(256);
        p[x].b:=random(256);
      end;
    end;
    canvas.draw(0,0,b);
  end;

  procedure TForm1.FormDestroy(sender:TObject);
  begin
    b.free;
  end;
  ........................................................
Вернуться к содержанию 


Вопрос:

Какой самый быстрый способ для очистки canvasа?
Ответ:
Windows API функция PatBlt().
Пример:

            procedure TForm1.Button1Click(Sender: TObject); 
            begin 
              PatBlt(Form1.Canvas.Handle, 
                      0, 
                      0, 
                      Form1.ClientWidth, 
                      Form1.ClientHeight, 
                      WHITENESS); 
            end;
Наверх к содержанию 
Вопрос:
При изменении размеров формы мне необходимо чтобы перерисовывалась вся ее поверхность. Но свойство Canvas.ClipRect у формы - только для чтения.
Ответ:
На событии Resize вызовите Windows API функцию InvalidateRect(). Если передать nil в качестве второго параметра приведет к тому, что перерисовываться будет вся клиентская область окна. Третий параметр указывает будет ли перерисовываться фон формы.
Пример:
            procedure TForm1.FormResize(Sender: TObject); 
            begin 
              InvalidateRect(Form1.Handle, nil, false); 
            end;
Наверх к содержанию 
Вопрос:
Как временно отключить перерисовку окна?
Ответ:
Вызовите функцию WinAPI LockWindowUpdate передав ей дескриптор окна, которое необходимо не обновлять. Передайте ноль в качестве параметра для восстановления нормального обновления.
              LockWindowUpdate(Memo1.Handle); 
              . 
              . 
              LockWindowUpdate(0);
Наверх к содержанию 
Вопрос:
Как глобально перехватить нажатие кнопки PrintScreen?
Ответ:
В примере для глобального перехвата нажатия клавиши printscreen регистрируется горячая клавиша (hot key).
Пример:
            type 
              TForm1=class(TForm) 
                procedure FormCreate(Sender: TObject); 
                procedure FormDestroy(Sender: TObject); 
              private 
                { Private declarations } 
                procedure WMHotKey(var Msg : TWMHotKey); message WM_HOTKEY; 
              public 
                { Public declarations } 
              end; 
 
            var 
              Form1: TForm1; 
 
            implementation 
 
            {$R *.DFM} 
 
            const id_SnapShot=101; 
 
            procedure TForm1.WMHotKey (var Msg : TWMHotKey); 
            begin 
              if Msg.HotKey=id_SnapShot then 
                ShowMessage('GotIt'); 
            end; 
 
            procedure TForm1.FormCreate(Sender: TObject); 
            begin 
              RegisterHotKey(Form1.Handle, 
                              id_SnapShot, 
                              0, 
                              VK_SNAPSHOT); 
            end; 
 
            procedure TForm1.FormDestroy(Sender: TObject); 
            begin 
              UnRegisterHotKey (Form1.Handle, id_SnapShot); 
            end;
Наверх к содержанию 
Вопрос:
как заставить Рабочий Стола Windows обновится?
Ответ:
См. пример.
Пример:
            procedure TForm1.Button1Click(Sender: TObject); 
            begin 
              SendMessage(FindWindow('Progman', 'Program Manager'), 
                          WM_COMMAND, 
                          $A065, 
                          0); 
            end;
Наверх к содержанию 
Вопрос:
Как сделать родительское окно с фоновым рисунком в клиентской области?
Ответ:
Для того чтобы сделать это выполните следующие шаги:
      Срздайте новый проект. 
      Установите FormStyle формы в fsMDIForm 
      Разместите Image на форме и загрузите в него картинку. 
      Найдите { Private Declarations } в обьявлении формы и добаьте следующие строки: 
 
                FClientInstance : TFarProc; 
                FPrevClientProc : TFarProc; 
                procedure ClientWndProc(var Message: TMessage); 
 
      Добаьте следующие строки в разделе implementation: 
 
            procedure TMainForm.ClientWndProc(var Message: TMessage); 
            var 
              Dc : hDC; 
              Row : Integer; 
              Col : Integer; 
            begin 
              with Message do 
                case Msg of 
                  WM_ERASEBKGND: 
                  begin 
                    Dc :=TWMEraseBkGnd(Message).Dc; 
                    for Row :=0 to ClientHeight div Image1.Picture.Height do 
                      for Col :=0 to ClientWidth div Image1.Picture.Width do 
                        BitBlt(Dc, 
                            Col * Image1.Picture.Width, 
                            Row * Image1.Picture.Height, 
                            Image1.Picture.Width, 
                            Image1.Picture.Height, 
                            Image1.Picture.Bitmap.Canvas.Handle, 
                            0, 
                            0, 
                            SRCCOPY); 
                      Result :=1; 
                  end; 
                  else 
                    Result :=CallWindowProc(FPrevClientProc, 
                                              ClientHandle, 
                                              Msg, 
                                              wParam, 
                                              lParam); 
              end; 
            end; 
 
            В методе формы OnCreate добавьте: 
 
                FClientInstance :=MakeObjectInstance(ClientWndProc); 
                FPrevClientProc :=Pointer(GetWindowLong(ClientHandle, 
                                          GWL_WNDPROC)); 
                SetWindowLong(ClientHandle, 
                              GWL_WNDPROC, LongInt(FClientInstance)); 
 
            Добавьте к проекту новую форму и установите ее свойство FormStyle в 
            fsMDIChild. 
 
            У Вас получился  MDI-проект с "обоями" в клиентской области MDI формы.
Наверх к содержанию 
Вопрос:
Перерисовка canvasf моей формы занимает довольно много времени. Как определить установлен ли у пользователя режим перерисовки всего окна при перемещении чтобы временно отключить перерисовку моего окна?
Ответ:
В приведенном примере определяется включен ли режим "Full Window Drag" (перерисовки всего окна при перемещении)
Пример:
            procedure TForm1.Button1Click(Sender: TObject); 
            var 
              b : bool; 
            begin 
              SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, @b, 0); 
              if not b then 
                ShowMessage('Full Window Drag is not enabled') else 
                ShowMessage('Full Window Drag is enabled'); 
            end;
Наверх к содержанию 
Вопрос:
Как изменить обои Windows програмно?
Ответ:
Изменить обои можно функцией SystemParametersInfo()Б переслав ей в качестве параметров константу SPI_SETDESKWALLPAPER и имя нового файла обоев.
Пример:
              SystemParametersInfo(SPI_SETDESKWALLPAPER, 
                                    0, 
                                    PChar('C:\SOMEPATH\SOME.BMP'), 
                                    SPIF_SENDWININICHANGE);
Наверх к содержанию 
Вопрос:
Как создать иконку из bitmap'а?
Ответ:
Нужно создать два bitmap'а: bitmap-маску ("AND" bitmap) и bitmap-картинку (XOR bitmap). Потом передать дескрипторы "AND" и "XOR" bitmap-ов API функции CreateIconIndirect()
Пример:
            procedure TForm1.Button1Click(Sender: TObject); 
            var 
              IconSizeX : integer; 
              IconSizeY : integer; 
              AndMask : TBitmap; 
              XOrMask : TBitmap; 
              IconInfo : TIconInfo; 
              Icon : TIcon; 
            begin 
              {Get the icon size} 
              IconSizeX :=GetSystemMetrics(SM_CXICON); 
              IconSizeY :=GetSystemMetrics(SM_CYICON); 
 
              {Create the "And" mask} 
              AndMask :=TBitmap.Create; 
              AndMask.Monochrome :=true; 
              AndMask.Width :=IconSizeX; 
              AndMask.Height :=IconSizeY; 
 
              {Draw on the "And" mask} 
              AndMask.Canvas.Brush.Color :=clWhite; 
              AndMask.Canvas.FillRect(Rect(0, 0, IconSizeX, IconSizeY)); 
              AndMask.Canvas.Brush.Color :=clBlack; 
              AndMask.Canvas.Ellipse(4, 4, IconSizeX - 4, IconSizeY - 4); 
 
              {Draw as a test} 
              Form1.Canvas.Draw(IconSizeX * 2, IconSizeY, AndMask); 
 
              {Create the "XOr" mask} 
              XOrMask :=TBitmap.Create; 
              XOrMask.Width :=IconSizeX; 
              XOrMask.Height :=IconSizeY; 
 
              {Draw on the "XOr" mask} 
              XOrMask.Canvas.Brush.Color :=ClBlack; 
              XOrMask.Canvas.FillRect(Rect(0, 0, IconSizeX, IconSizeY)); 
              XOrMask.Canvas.Pen.Color :=clRed; 
              XOrMask.Canvas.Brush.Color :=clRed; 
              XOrMask.Canvas.Ellipse(4, 4, IconSizeX - 4, IconSizeY - 4); 
 
              {Draw as a test} 
              Form1.Canvas.Draw(IconSizeX * 4, IconSizeY, XOrMask); 
 
              {Create a icon} 
              Icon :=TIcon.Create; 
              IconInfo.fIcon :=true; 
              IconInfo.xHotspot :=0; 
              IconInfo.yHotspot :=0; 
              IconInfo.hbmMask :=AndMask.Handle; 
              IconInfo.hbmColor :=XOrMask.Handle; 
              Icon.Handle :=CreateIconIndirect(IconInfo); 
 
              {Destroy the temporary bitmaps} 
              AndMask.Free; 
              XOrMask.Free; 
 
              {Draw as a test} 
              Form1.Canvas.Draw(IconSizeX * 6, IconSizeY, Icon); 
 
              {Assign the application icon} 
              Application.Icon :=Icon; 
 
              {Force a repaint} 
              InvalidateRect(Application.Handle, nil, true); 
 
              {Free the icon} 
              Icon.Free; 
            end;
Наверх к содержанию 
Вопрос:
Как преобразовать RGB-цвет в оттенки серого?
Ответ:
В приведенном примере для преобразования RGB-цвета используются коэффициенты, принятые в телевидении:
            function RgbToGray(RGBColor : TColor) : TColor; 
            var 
              Gray : byte; 
            begin 
              Gray :=Round((0.30 * GetRValue(RGBColor)) + 
                            (0.59 * GetGValue(RGBColor)) + 
                            (0.11 * GetBValue(RGBColor ))); 
              Result :=RGB(Gray, Gray, Gray); 
            end; 
 
            procedure TForm1.FormCreate(Sender: TObject); 
            begin 
              Shape1.Brush.Color :=RGB(255, 64, 64); 
              Shape2.Brush.Color :=RgbToGray(Shape1.Brush.Color); 
            end;
Наверх к содержанию


Как вывести на Canvas надпись под углом?
Nikita Popov 3 января 1999 г
nix@tekton.dol.ru
Вот, взгляните на пример:
...
function CreateRotatedFont(F : TFont; Angle : Integer) : hFont;
  {-create a rotated font based on the font object F}
var
  LF : TLogFont;
begin
  FillChar(LF, SizeOf(LF), #0);
  with LF do 
  begin
    lfHeight :=F.Height;
    lfWidth :=0;
    lfEscapement :=Angle * 10;
    lfOrientation :=0;
    if fsBold in F.Style then
      lfWeight :=FW_BOLD
    else
      lfWeight :=FW_NORMAL;
    lfItalic :=Byte(fsItalic in F.Style);
    lfUnderline :=Byte(fsUnderline in F.Style);
    lfStrikeOut :=Byte(fsStrikeOut in F.Style);
    lfCharSet :=DEFAULT_CHARSET;
    StrPCopy(lfFaceName, F.Name);
    lfQuality :=DEFAULT_QUALITY;
    {everything else as default}
    lfOutPrecision :=OUT_DEFAULT_PRECIS;
    lfClipPrecision :=CLIP_DEFAULT_PRECIS;
    case F.Pitch of
      fpVariable : lfPitchAndFamily :=VARIABLE_PITCH;
      fpFixed    : lfPitchAndFamily :=FIXED_PITCH;
    else
      lfPitchAndFamily :=DEFAULT_PITCH;
    end;
  end;
  Result :=CreateFontIndirect(LF);
end;
...
  {create the rotated font}
  if FontAngle <>0then
    Canvas.Font.Handle :=CreateRotatedFont(Font,FontAngle);
...
Вращаются только векторные шрифты.


Как вывести графику на принтер?
Dmitry Kiselev 24 декабря 1998 г
kiselevd@glight.bmstu.ru

Функция Printer.Canvas.StretchDraw(Rect,Bitmap) не всегда правильно выводит в печать графику. По этому я предлагаю свой модуль с функцией печати битмапа. Битмап тут вмещается и перемасштабируется, чтоб попасть на страницу с увеличенным размером и разместиться по центру листа. Эти установки пользователь может изменить по своему желанию.

unit UPrint;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Printers;

 

 
 
 
 
 
 
 
 
 
 
 
 
 

procedure PrintBitmap(ABitmap: TBitmap);
implementation
procedure PrintBitmap(ABitmap: TBitmap);
var
B : TBitmap;
isPrnPal : Boolean;
Pal, OldPal : hPalette;
PageWidth, PageHeight : Integer;
PageMargin : TPoint;
TestInt : Integer;
ImagePageWidth : Integer;
ImagePageHeight : Integer;
ScaleX, ScaleY, OffsetX, OffsetY : Integer;
ImageSize, InfoSize : DWord;
PImage, PInfo : Pointer;
begin
Pal :=0;
OldPal :=0;
Printer.BeginDoc;
B :=TBitmap.Create;
B.Assign(ABitmap);
B.PixelFormat :=pf24bit;
isPrnPal :=False;
if (GetDeviceCaps(Printer.Canvas.Handle, RasterCaps) and RC_Palette)=RC_Palette then
begin
B.PixelFormat :=pf8bit;
Pal :=CopyPalette(B.Palette);
OldPal :=SelectPalette(Printer.Canvas.Handle, Pal, False);
isPrnPal :=True;
end;
PageWidth :=Integer(GetDeviceCaps(Printer.Canvas.Handle, HORZRES));
PageHeight :=Integer(GetDeviceCaps(Printer.Canvas.Handle, VERTRES));
PageMargin.X :=0; PageMargin.Y :=0;
TestInt :=Integer(GetPrintingOffset);
if Escape(Printer.Canvas.Handle, QUERYESCSUPPORT, SizeOf(TestInt), @TestInt, nil) <> 0 then
begin
if Escape(Printer.Canvas.Handle, GETPRINTINGOFFSET, 0, nil, @PageMargin) <=0 then
begin
PageMargin.X :=0;
PageMargin.Y :=0;
end;
end;
ImagePageWidth :=PageWidth - 2 * PageMargin.X;
ImagePageHeight :=PageHeight - 2 * PageMargin.Y;
if ((ImagePageWidth <=ImagePageHeight) and (B.Width>= B.Height)) or ((ImagePageWidth> ImagePageHeight) and (B.Width > B.Height)) then
begin
ScaleX :=ImagePageWidth;
ScaleY :=Trunc(B.Height * ImagePageWidth / B.Width);
OffsetX :=PageMargin.X;
OffsetY :=(PageHeight div 2) - (ScaleY div 2);
end else
begin
ScaleY :=ImagePageHeight;
ScaleX :=Trunc(B.Width * ImagePageHeight / B.Height);
OffsetY :=PageMargin.Y;
OffsetX :=(PageWidth div 2) - (ScaleX div 2);
end;
GetDIBSizes(B.Handle, InfoSize, ImageSize);
GetMem(PImage, ImageSize);
GetMem(PInfo, InfoSize);
GetDIB(B.Handle, B.Palette, PInfo^, PImage^);
StretchDIBits(Printer.Canvas.Handle, OffsetX, OffsetY, ScaleX, ScaleY, 0, 0, B.Width, B.Height, PImage, PBitmapInfo(PInfo)^, DIB_RGB_COLORS, SRCCOPY);
FreeMem(PImage); FreeMem(PInfo);
if isPrnPal then
begin
SelectPalette(Printer.Canvas.Handle, OldPal, False);
DeleteObject(Pal);
end;
Printer.EndDoc;
end;
end.


Как подгрузить 256 цветный битмап из ресурса и отобразить его в нормальной палитре?
Обычно это делается таким образом:

Image1.BitMap.Hande :=LoadBitMap( hInstance, 'BMP_NAME');

LoadBitmap загружает только картинку, без палитры. Если палитра BitMap'а отличается от системной, то ее надо устанавливать "вручную". Могут возникнуть проблемы, если на одной форме расположены две картинки с разными палитрами.

procedure XLoadBitmap(Instance : THandle; BitmapName : PChar; var HB : HBitmap; var HP : HPalette);
var
DC : HDC;
BI : PBitMapInfo;
Pal : PLogPalette;
I : Integer;
ResIdHandle : THandle;
ResDataHandle : THandle;
Bitmap : HBitmap;
C : HWnd;
OldPalette, Palette : HPalette;
begin
Bitmap :=0;
Palette :=0;
HB :=0;
HP :=0;
{Получить ресурс из модуля}
ResIDHandle :=FindResource(Instance, BitmapName, rt_BitMap );
if ResIDHandle <> 0 then
begin
ResDataHandle :=LoadResource(Instance, ResIDHandle );
if ResDataHandle <> 0 then
begin
BI :=LockResource( ResDataHandle );
if BI <>nil then
begin
{256-цветный битмап?}
if BI^.bmiHeader.biBitCount=8 then
begin
{Создать палитру}
GetMem( Pal, SizeOf(TLogPalette) + 256 * SizeOf( TPaletteEntry ));
for I :=0 to 255 do
with Pal^.palPalEntry[I] do
begin
peRed :=BI^.bmiColors[I].rgbRed;
peGreen :=BI^.bmiColors[I].rgbGreen;
peBlue :=BI^.bmiColors[I].rgbBlue;
peFlags :=0;
end;
Pal^.palNumEntries :=256;
Pal^.palVersion :=$300;
Palette :=CreatePalette(Pal^);
FreeMem(Pal, SizeOf(TLogPalette) + 256 * SizeOf(TPaletteEntry));
{Привести цвета палитры в системные}
DC :=CreateDC('Display', nil, nil, nil);
OldPalette :=SelectPalette(DC, Palette, False);
UnrealizeObject(Palette);
RealizePalette(DC);
{Создать битмап}
BitMap :=CreateDIBitmap(DC, BI^.bmiHeader, CBM_INIT, @PByteArray(BI)^[SizeOf(TBitMapInfo) + SizeOf(TRGBQuad) * 256 - 4], BI^, DIB_RGB_COLORS);
{Освободить ресурсы}
UnlockResource(ResDataHandle);
FreeResource(ResDataHandle);
SelectPalette(DC, OldPalette, False);
DeleteDC(DC);
end
else
begin
{Не 256-цветный битмап}
UnlockResource(ResDataHandle);
FreeResource(ResDataHandle);
BitMap :=LoadBitmap(Instance, BitmapName);
end;
HB :=Bitmap;
HP :=Palette;
end; {BI <> nil }
end; {ResDataHandle <> 0}
end; {ResIDHandle <> 0 }
end;
procedure TForm1.FormCreate(Sender: TObject);
var
HB : HBitmap;
HP : HPalette;
begin
xLoadBitmap(hInstance, 'PHOTO', HB, HP);
Image1.Picture.Bitmap.Handle :=HB;
Image1.Picture.Bitmap.Palette :=HP;
end;
Код Вадима Пузанова /Красноярск/


Как поместить двумерный массив в Image.
Представим, что данные находятся в массиве:
TestArray : array[0..127, 0..127] of Byte;

Картинка будет иметь размер 128 x 128 точек:

Image1.Picture.Bitmap.Width :=128;
Image1.Picture.Bitmap.Height :=128;

Вызываем функцию Windows API для формирования BitMap:

SetBitmapBits(Image1.Picture.Bitmap.Handle, sizeof(TestArray), @TestArray);
Image1.Refresh; {для того, чтобы изменения отобразились}

Однако, если вы используете свою палитру, то ее нужно создать


Используются технологии uCoz
Используются технологии uCoz

Rambler's Top100 Rambler's Top100
Используются технологии uCoz

Rambler's Top100 Rambler's Top100

©  Adept Design Studio

Используются технологии uCoz