掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
TListViewで行の高さを低く設定したときの実際の高さを取得するには (ID:150580)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
質問がわかりづらかったのでわかりやすく書き直します。 【やりたいこと】 TListViewでセルに編集機能を持たせるためTEditを置いて編集するクラスを制作しています 【困っていること】 クリックしたときにそのセルのサイズに合わせてTEditの位置を変えています。 しかし Topの座標指定がずれることがあります。 調べていくと、TListViewにImageListを関連づけして、ImageListの高さを変えて TListViewの行の高さを変更する方法だと 表示可能な行よりも低く設定された場合、TListView は ImageListの Heightの値では無く表示可能な高さで表示されます。 そのためズレるようです ImageListを使わずに 設定値通りの高さで表示する方法 または 実際に表示されている行の高さが取得出来れば助かります。 クリックしたときにTEditをそのセルの位置へ移動させるサンプルを作りました。 【環境】 OS :Windows10 コンパイラ DelphiXE5、Delphi10.4 uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ImgList, Vcl.ComCtrls, Vcl.StdCtrls,CommCtrl; type TListViewEx = class(TListView) private { Private 宣言 } FImages : TImageList; FEdit : TEdit; FItemheight : Integer; function TopIndex() : Integer; function ColumnLeft(const aCol : Integer) : Integer; function GetScrollBarLeft() : Integer; function GetColumAt(const X,Y : Integer) : Integer; function GetColumnHeight(): Integer; //function GetItemHeight: Integer; procedure SetItemHeight(const Value: Integer); procedure OnSelfClick(Sender: TObject); procedure OnSelfDrawItem(Sender: TCustomListView; Item: TListItem; Rect: TRect; State: TOwnerDrawState); function GetColumn: Integer; protected procedure CNMeasureitem(var Message: TWMMeasureItem); message CN_MEASUREITEM; public { Public 宣言 } constructor Create(AOwner: TComponent); override; destructor Destroy;override; procedure Clear();override; property ItemHeight : Integer read FItemHeight write SetItemHeight; property Column : Integer read GetColumn; end; type TForm8 = class(TForm) procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormShow(Sender: TObject); private { Private 宣言 } FListView : TListViewEx; public { Public 宣言 } end; var Form8: TForm8; implementation {$R *.dfm} { TListViewEx } procedure TListViewEx.CNMeasureitem(var Message: TWMMeasureItem); begin inherited; Message.MeasureItemStruct.itemHeight := FItemHeight; end; function TListViewEx.ColumnLeft(const aCol: Integer): Integer; var i,x: Integer; begin result := 0; if aCol = 0 then exit; x := 0; for i := 0 to aCol-1 do begin x := x + Columns[i].Width; end; result := x; end; constructor TListViewEx.Create(AOwner: TComponent); begin inherited; FImages := TImageList.Create(Self); OnClick := OnSelfClick; OnDrawItem := OnSelfDrawItem; OwnerDraw := True; ItemHeight := 11; // 行の高さを指定 FEdit := TEdit.Create(Self); FEdit.Parent := Self; FEdit.Visible := False; end; destructor TListViewEx.Destroy; begin FEdit.Free; FImages.Free; inherited; end; procedure TListViewEx.Clear; begin Items.Clear; FImages.Clear; end; function TListViewEx.GetColumAt(const X, Y: Integer): Integer; var i,xx : Integer; begin result := -1; xx := -GetScrollBarLeft(); // 基準値をスクロールバーの現在位置から取得 for i := 0 to Columns.Count-1 do begin // 列数ループ xx := xx + Columns[i].Width; // 基準値に列幅を加算 if X < xx then begin // カーソルが列内にある場合 result := i; // カーソルの列位置として返す exit; // 処理終了 end; end; end; function TListViewEx.GetColumn: Integer; var p : TPoint; begin p := ScreenToClient(Mouse.CursorPos); // マウス位置取得 result := GetColumAt(p.X,p.Y); // マウス位置から列を取得 end; function TListViewEx.GetColumnHeight: Integer; var Header_Handle: HWND; WindowPlacement: TWindowPlacement; begin Header_Handle := ListView_GetHeader(Handle); FillChar(WindowPlacement, SizeOf(WindowPlacement), 0); WindowPlacement.Length := SizeOf(WindowPlacement); GetWindowPlacement(Header_Handle, @WindowPlacement); Result := WindowPlacement.rcNormalPosition.Bottom - WindowPlacement.rcNormalPosition.Top+1; end; { function TListViewEx.GetItemHeight: Integer; begin if SmallImages<>nil then begin result := FImages.Height; // ここで実際の行の高さが取得出来るのが理想 end else begin result := 16; end; end; } function TListViewEx.GetScrollBarLeft: Integer; var SInfo: TScrollInfo; begin SInfo.cbSize := SizeOf(SInfo); SInfo.fMask := SIF_ALL; GetScrollInfo(Handle, SB_HORZ, SInfo); result := SInfo.nPos; end; procedure TListViewEx.OnSelfClick(Sender: TObject); var aCol : Integer; begin aCol := GetColumn; if aCol=-1 then exit; FEdit.Left := (ColumnLeft(aCol) - GetScrollBarLeft()); FEdit.Top := (ItemIndex - TopIndex) * (ItemHeight+1) +GetColumnHeight(); // 問題の部分 FEdit.Width := Columns[aCol].Width; FEdit.Height := ItemHeight; FEdit.Visible := True; end; procedure TListViewEx.OnSelfDrawItem(Sender: TCustomListView; Item: TListItem; Rect: TRect; State: TOwnerDrawState); var i: Integer; r : Trect; cv : TCanvas; begin r := Rect; cv := Canvas; if (odFocused in State) or (odSelected in State) then begin cv.Brush.Color := clActiveCaption; cv.Font.Color := clWhite; end else begin cv.Brush.Color := clWhite; cv.Font.Color := clBlack; end; cv.Brush.Style := bsSolid; cv.FillRect(Rect); cv.Brush.Style := bsClear; r.Right := Columns[0].Width; Canvas.TextOut(r.Left, r.Top, Item.Caption); for i := 0 to Item.SubItems.Count-1 do begin r.Left := r.Left +Columns[i].Width; r.Right :=r.Left + Columns[i+1].Width; Canvas.TextOut(r.Left, r.Top, Item.SubItems[i]); end; end; procedure TListViewEx.SetItemHeight(const Value: Integer); var LTopIndex : Integer; begin if Value <> FItemHeight then begin FItemHeight := Value; if Items.Count > 1 then begin LTopIndex := TopItem.Index; Selected := nil; RecreateWnd; Scroll(0, LTopIndex * FItemHeight); end; end; // ImageListで行の高さを変更する処理 SmallImages := nil; FImages.Height := Value; FImages.Width := Value; SmallImages := FImages; end; function TListViewEx.TopIndex: Integer; var SInfo: TScrollInfo; begin SInfo.cbSize := SizeOf(SInfo); SInfo.fMask := SIF_ALL; GetScrollInfo(Handle, SB_VERT, SInfo); result := SInfo.nPos; end; procedure TForm8.FormCreate(Sender: TObject); var dc : TListColumn; begin FListView := TListViewEx.Create(Self); FListView.Parent := Self; FListView.Align := alClient; FListView.ViewStyle := vsReport; FListView.RowSelect := True; dc := FListView.Columns.Add; dc.Caption := '列1'; dc.Width := 100; dc := FListView.Columns.Add; dc.Caption := '列2'; dc.Width := 200; end; procedure TForm8.FormDestroy(Sender: TObject); begin FListView.Free; end; procedure TForm8.FormShow(Sender: TObject); var dl : TListItem; i: Integer; begin for i := 0 to 30 do begin dl := FListView.Items.Add; dl.Caption := IntToStr(i+1)+'行目'; dl.SubItems.Add('データ1'); end; end;
←解決時は質問者本人がここをチェックしてください。
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.