有请DFW wangdonghai(100)

  • 主题发起人 主题发起人 qqingmu
  • 开始时间 开始时间
Q

qqingmu

Unregistered / Unconfirmed
GUEST, unregistred user!
上次那个拖动复制的问题我试了有Handle的都可以,但是在我DBGrid表格中试了很多方法都不能在拖动时获取当前鼠标所在的单元格,所以数据send不过去,这个有什么办法吗?
 
没handle的话~~就没有办法了~~
 
unit uDragUtils;interfaceuses Windows,ActiveX,Messages;const WM_DragMsg=WM_USER+100;type TMyDragText=class(TObject,IUnknown,IDropTarget) private FHandle:THandle; CanDrop:HResult; FE:TFormatEtc; FRefCount:Integer; protected {IUnknown} function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; {IDropTarget} function DragEnter(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; function DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; function DragLeave: HResult; stdcall; function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; public constructor Create(AHandle:THandle); destructor Destroy;override;end;implementation{ TMyDragText }function TMyDragText._AddRef: Integer;begin result:=InterLockedDecrement(FRefCount); if Result=0 then Destroy;end;function TMyDragText._Release: Integer;begin result:=InterLockedIncrement(FRefCount);end;constructor TMyDragText.Create(AHandle:THandle);begin FRefCount:=0; FHandle:=AHandle; RegisterDragDrop(FHandle,self);end;destructor TMyDragText.Destroy;begin RevokeDragDrop(FHandle); inherited;end;function TMyDragText.DragEnter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;begin result:=E_FAIL; CanDrop:=E_FAIL; if Assigned(dataObj) then begin FE.cfFormat:=CF_TEXT; FE.ptd:=nil; FE.dwAspect:=DVASPECT_CONTENT; FE.lindex:=-1; FE.tymed:=TYMED_HGLOBAL; CanDrop:=dataObj.QueryGetData(FE); result:=CanDrop; if not FAILED(result) then dwEffect:=DROPEFFECT_COPY else dwEffect:=DROPEFFECT_NONE; end;end;function TMyDragText.DragLeave: HResult;begin result:=S_OK;end;function TMyDragText.DragOver(grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;begin result:=S_OK;end;function TMyDragText.Drop(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;var medium:stgMedium; hData:HGLOBAL;begin result:=E_FAIL; if not FAILED(CanDrop) then begin result:=dataObj.GetData(FE,medium); hData:=HGLOBAL(GlobalLock(medium.hGlobal)); SendMessage(FHandle,WM_DragMsg,hData,0); GlobalUnlock(hData); GlobalFree(hData); end;end;function TMyDragText.QueryInterface(const IID: TGUID; out Obj): HResult;begin if GetInterface(IID,Obj) then result:=S_OK else result:=E_NOINTERFACE;end;end.unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, ADODB, Grids, DBGrids,uDragUtils;type TForm1 = class(TForm) DBGrid1: TDBGrid; ADOConnection1: TADOConnection; ADOQuery1: TADOQuery; DataSource1: TDataSource; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private FDragText:TMyDragText; public procedure DoDragText(var Msg:TMessage);message WM_DragMsg; end;var Form1: TForm1;implementation{$R *.dfm}uses ActiveX;procedure TForm1.DoDragText(var Msg: TMessage);begin ADOQuery1.Edit; ADOQuery1.FieldByName('UserName').AsString:= PChar(Msg.WParam);end;procedure TForm1.FormCreate(Sender: TObject);begin OleInitialize(nil); FDragText:=TMyDragText.Create(Handle);//这时传入的是窗体的句柄end;procedure TForm1.FormDestroy(Sender: TObject);begin FDragText.Free; OleUninitialize;end;end.对DBGrid的处理最终都要在DBGrid对应的数据集里进行处理
 
看来我描述的不是很清楚我想的是。当我的鼠标由外面拖进来的时候,我怎么知道它在哪个行列上DragDrop.这时我再对它进行类型判断然后赋值。但我的在拖动的时候,本窗口的事件完全不响应,这该怎么办?:(
 
DBGrid的每一列都对应一个字段,对DBGrid的处理最终都要在DBGrid对应的数据集里进行处理 ,你的DBGrid有几个字段能够接收拖放操作呀,是一列可以还是多列可以呀如果是一列可以的话,我给出的代码就可以实现了,代码中的SendMessage(FHandle,WM_DragMsg,hData,0);就是告诉DBGrid对应的窗体拖放已经结束,而这段代码就是处理拖放用的procedure TForm1.DoDragText(var Msg: TMessage);begin ADOQuery1.Edit; ADOQuery1.FieldByName('UserName').AsString:= PChar(Msg.WParam);end;我把上面的代码改了一下,你自己再参考一下procedure TForm1.DoDragText(var Msg: TMessage);var pt:TPoint; ColIndex:Integer; sFN:string;begin GetCursorPos(pt); pt:=ScreenToClient(pt); ColIndex:=DBGrid1.MouseCoord(pt.X,pt.Y).Y;//得到拖放列 //showmessage(inttostr(ColIndex)); if ColIndex=-1 then exit; sFN:=DBGrid1.Columns[ColIndex].FieldName; ADOQuery1.Edit; ADOQuery1.FieldByName(sFN).AsString:= PChar(Msg.WParam);end;我试了一下DBGrid的MouseCoord方法返回的列索引有时候不对
 
wangdonghai热情!----值得尊敬与学习.楼主也要多些专研的精神.
 
嗯,是呀,我太业余了呵呵,非常感谢wangdonghai我对windows的消息基本没怎么使用过,从这个问题也学到了不少。DBgird的数据赋值我知道是要在数据集中进行,不过我想做一个比较友好的操作界面,就需要对当前接收消息的控件作一些操作了,比如说grid是有多行多列的, 我在控件上拖动的时候,想要有选择的效果,让操作者知道数据将会填充到哪一个单元格,所以才有上面的一问。 就好像Excel那样,拖进去的时候,都有一个灰色的框[:)]
 
这个问题已经基本解决,根据wangdonghai的提示,我用MouseToCell就可以直接取到鼠标落下的坐标位置的行列了。不过要怎么才能得到鼠标移动未落下时的行列呢,能不能给个提示。。。呵呵,是不是贪心了一点 --! ,明天结帐。再一次感谢wangdonghai的耐心指导
 
>>Re :我试了一下DBGrid的MouseCoord方法返回的列索引有时候不对 XY除去控件本身的Left 和Top 就对了
 
unit uDragUtils;interfaceuses Windows,ActiveX,Messages;const WM_DragMsg=WM_USER+100; WM_DragEnter=WM_USER+101;type TMyDragText=class(TObject,IUnknown,IDropTarget) private FHandle:THandle; CanDrop:HResult; FE:TFormatEtc; FRefCount:Integer; protected {IUnknown} function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; function _AddRef: Integer; stdcall; function _Release: Integer; stdcall; {IDropTarget} function DragEnter(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; function DragOver(grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; function DragLeave: HResult; stdcall; function Drop(const dataObj: IDataObject; grfKeyState: Longint; pt: TPoint; var dwEffect: Longint): HResult; stdcall; public constructor Create(AHandle:THandle); destructor Destroy;override;end;implementation{ TMyDragText }function TMyDragText._AddRef: Integer;begin result:=InterLockedDecrement(FRefCount); if Result=0 then Destroy;end;function TMyDragText._Release: Integer;begin result:=InterLockedIncrement(FRefCount);end;constructor TMyDragText.Create(AHandle:THandle);begin FRefCount:=0; FHandle:=AHandle; RegisterDragDrop(FHandle,self);end;destructor TMyDragText.Destroy;begin RevokeDragDrop(FHandle); inherited;end;function TMyDragText.DragEnter(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;begin result:=E_FAIL; CanDrop:=E_FAIL; if Assigned(dataObj) then begin FE.cfFormat:=CF_TEXT; FE.ptd:=nil; FE.dwAspect:=DVASPECT_CONTENT; FE.lindex:=-1; FE.tymed:=TYMED_HGLOBAL; //SendMessage(FHandle,WM_DragEnter,0,0); CanDrop:=dataObj.QueryGetData(FE); result:=CanDrop; if not FAILED(result) then dwEffect:=DROPEFFECT_COPY else begin dwEffect:=DROPEFFECT_NONE; end; end;end;function TMyDragText.DragLeave: HResult;begin result:=S_OK;end;function TMyDragText.DragOver(grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;begin result:=S_OK; SendMessage(FHandle,WM_DragEnter,0,0);end;function TMyDragText.Drop(const dataObj: IDataObject; grfKeyState: Integer; pt: TPoint; var dwEffect: Integer): HResult;var medium:stgMedium; hData:HGLOBAL;begin result:=E_FAIL; if not FAILED(CanDrop) then begin result:=dataObj.GetData(FE,medium); hData:=HGLOBAL(GlobalLock(medium.hGlobal)); SendMessage(FHandle,WM_DragMsg,hData,0); GlobalUnlock(hData); GlobalFree(hData); end;end;function TMyDragText.QueryInterface(const IID: TGUID; out Obj): HResult;begin if GetInterface(IID,Obj) then result:=S_OK else result:=E_NOINTERFACE;end;end.unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, ADODB, Grids, DBGrids,uDragUtils, StdCtrls;type TForm1 = class(TForm) DBGrid1: TDBGrid; ADOConnection1: TADOConnection; ADOQuery1: TADOQuery; DataSource1: TDataSource; Edit1: TEdit; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); private FDragText:TMyDragText; FCol,FRow:Integer; public procedure DoDragText(var Msg:TMessage);message WM_DragMsg; procedure DoDragEnter(var Msg:TMessage);message WM_DragEnter; end;var Form1: TForm1;implementation{$R *.dfm}uses ActiveX;procedure TForm1.DoDragEnter(var Msg: TMessage);var pt:TPoint; rpt:TGridCoord;begin GetCursorPos(pt); pt.X:=pt.X-DBGrid1.Left; pt.Y:=pt.Y-DBGrid1.Top; pt:=ScreenToClient(pt); rpt:=DBGrid1.MouseCoord(pt.X,pt.Y); FCol:=rpt.X; FRow:=rpt.Y; edit1.Text:='Row:'+inttostr(rpt.y)+',Col:'+inttostr(rpt.x); DBGrid1.Refresh;end;procedure TForm1.DoDragText(var Msg: TMessage);var pt:TPoint; rpt:TGridCoord; sFN:string;begin GetCursorPos(pt); pt.X:=pt.X-DBGrid1.Left; pt.Y:=pt.Y-DBGrid1.Top; pt:=ScreenToClient(pt); rpt:=DBGrid1.MouseCoord(pt.X,pt.Y); if rpt.X<=0 then exit; if rpt.Y<=0 then exit; sFN:=DBGrid1.Columns[rpt.x-1].FieldName; ADOQuery1.DisableControls; try ADOQuery1.First; ADOQuery1.MoveBy(rpt.Y-1); finally ADOQuery1.EnableControls; end; ADOQuery1.Edit; ADOQuery1.FieldByName(sFN).AsString:= PChar(Msg.WParam); ADOQuery1.Post; FCol:=-1; FRow:=-1;end;procedure TForm1.FormCreate(Sender: TObject);begin OleInitialize(nil); FDragText:=TMyDragText.Create(Handle); FCol:=-1; FRow:=-1;end;procedure TForm1.FormDestroy(Sender: TObject);begin FDragText.Free; OleUninitialize;end;procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);begin if (DataCol=FCol-1) and (ADOQuery1.RecNo=FRow) then begin DBGrid1.Canvas.Brush.Color:=clBlue; DBGrid1.Canvas.FillRect(Rect); end;end;end.希望能满足楼主的要求
 
嘿嘿。[:D]3Q
 
后退
顶部