BLOG main image
분류 전체보기 (65)
JSP (6)
Android (1)
ASP.NET (0)
MSSQL (4)
PHP (18)
ASP (11)
오픈 API (1)
HTML (2)
JavaScript (0)
Windows Programming (8)
컴퓨터교양 (14)
객체 지향 (0)
리뷰 및 생각 (0)
Visitors up to today!
Today hit, Yesterday hit
daisy rss
tistory 티스토리 가입하기!
2010. 9. 13. 02:15

델파이에서 기본적으로 제공하는 DBGrid는 UI 면에서 볼 때 그리 강력하지 않다.
보통의 다른 그리드에서 제공하는 기본적인 기능이 구현되어 있지 않다.
예를 들면 컬럼명을 클릭하면 오름차순이나 내림차순으로 정렬되는 기능(Sort function)이 없고,
컬럼의 오른쪽 끝을 더블 클릭하면 내용의 길이에 따라 컬럼너비가 늘어나는 기능(Column autoFit function)이 없다.
또한 디자이너에서 그리드 외곽선을 솔리드로 만드는 기능이 없다.

이중 Column autoFit 을 구현하는 방법에 대해 기록한다.

목표 : 컬럼명을 더블 클릭하면 해당 컬림이 autoFit이 되도록 한다.
1. DBGrid1DblClick 이벤트 속에서 컬럼명이 더블클릭 되었는지 판단한다.(gridCoord.Y == 0)
2.
컬럼명이 더블클릭 되었으면 해당 컬럼을 다시 그린다.(Repaint)
3. 다시 그릴때 그려지는 텍스트들의 너비를 비교하여, 최대 너비를 구한다.(DrawColumnCell)
4. 구해진 너비를 컬럼너비에 대입한다.

아래 소스처럼 구현 하면 된다. 자세한 설명은 나중에...



출처 : http://delphi.about.com/od/usedbvcl/a/dbgrid_autofit.htm

 type
  TColumnWidthHelper = record
   Index : integer;
   MaxWidth : integer;
  end;

procedure TForm1.DBGrid1DblClick(Sender: TObject) ;
var
   mouseInGrid : TPoint;
   gridCoord: TGridCoord;
begin
  //Convert "Screen" Mouse to "Grid" Mouse
  mouseInGrid := DBGrid1.ScreenToClient(Mouse.CursorPos) ;
  gridCoord := DBGrid1.MouseCoord(mouseInGrid.X, mouseInGrid.Y) ;

  //Column titles NOT displayed?
  if not (dgTitles in DBGrid1.Options) then Exit;

  //Titles displayed but we double-clicked on "regular" row?
  if gridCoord.Y <> 0 then Exit;

  //find Column index
  if dgIndicator in DBGrid1.Options then
    ColumnWidthHelper.Index := -1 + gridCoord.x
  else
    ColumnWidthHelper.Index := gridCoord.x;

  //Indicator Column?
  if ColumnWidthHelper.Index < 0 then Exit;
... // continues below When we are sure that a column title was double clicked we can find the widest entry in that column and set column width ...
    //continues from above ...

    ColumnWidthHelper.MaxWidth := -1;
 
    //"recalculate" ColumnWidthHelper.MaxWidth
    DBGrid1.Repaint;
 
    //"auto size" Column width
    DBGrid1.Columns[ColumnWidthHelper.Index].Width := 4 + ColumnWidthHelper.MaxWidth;
 end;
 
//The trick is in the DBGrid1.Repaint call. This forces the grid to repaint itself thus fireing the DrawColumnCell event (for all the visible rows).
 procedure TForm1.DBGrid1DrawColumnCell(
    Sender: TObject;
    const Rect: TRect;
    DataCol: Integer;
    Column: TColumn;
    State: TGridDrawState) ;
 begin
   //is this is the column we want to auto-size?
   if DataCol = ColumnWidthHelper.Index then
   begin
    //Column has field?
    if Assigned(Column.Field) then
    begin
     //find the widest string
     ColumnWidthHelper.MaxWidth := Max(ColumnWidthHelper.MaxWidth, DBGrid1.Canvas.TextWidth(Column.Field.DisplayText)) ;
    end;
   end;
 end; 
2010. 9. 13. 00:56

델파이에서 기본적으로 제공하는 DBGrid에는 한가지 문제점이 있다.
그리드에서 마우스 스크롤을 한 뒤 원하는 셀을 클릭해보면 원치 않는 행이 선택되는 것을 볼 수 있다.
마우스 스크롤을 아랫쪽으로 스크롤을 하면 실제 커서 포인터는 위로 이동하고,
반대로 마우스 스크롤을 윗쪽으로 스크롤을 하면 실제 커서 포인터는 아래로 이동한다.

이것은 DBGrid가 Visible 부분은 잘 처리하는데, 커서 부분은 잘 처리하지 못하는 문제이다.
따라서 마우스 스크롤시 커서 부분을 잘 처리시켜줘야 한다.

잘 처리하는 방법은 WndProc에 새로운 메시지 처리기를 등록하고, WM_MOUSEWHEEL 쪽을 알맞게 구현하면 된다.
아래 소스처럼 구현 하면 된다. 자세한 설명은 나중에...



출처 : http://www.delphi3000.com/articles/article_3892.asp?SK=DBGrid

type
  TomaInvento = class(TControl);

//So we can, later on, substitute the WndProc of DBGrid1 with an instruction similar to:

  DBGrid1.WindowProc := DBGrid1PillaLaRueda;

//for example in "Oncreate" of our Form
//Here you have the Unit of a form in which I have placed a DBGrid a TTable and a TDataSource to check all the invention


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids, DBGrids, Db, DBTables;

type
  TForm1 = class(TForm)
    Table1: TTable;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure DBGrid1PillaLaRueda(var Message: TMessage);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

type
  TomaInvento = class(TControl);

procedure TForm1.DBGrid1PillaLaRueda(var Message: TMessage);
var
  Cuanto : short;
begin
  if (Message.Msg = WM_MOUSEWHEEL) then begin
    Cuanto:=HIWORD(Message.WParam);
    Cuanto:=Cuanto div 120;
    DbGrid1.DataSource.DataSet.MoveBy(-Cuanto)
  end else TomaInvento(DBGrid1).WndProc(Message);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DBGrid1.WindowProc := DBGrid1PillaLaRueda;
end;

end.