type tcustomcontrol=class(TWinControl) uses utslvclauxiliary,utslvclgdi; {** @explan(说明) 自绘制窗口控件 %% **} //20220908添加splitter功能 private [weakref]FOnPaint:TNotifyEvent; protected procedure PaintWindow(DC:HDC);override; begin //odh := canvas.Handle; Canvas.Handle := dc; canvas.font := font; canvas.brush.Color := Color; Canvas.requiregdi(); Canvas.rcpaint := PAINTSTRUCT().rcpaint(); try Paint(); finally Canvas.Handle := 0; end; end procedure Paint();override; begin inherited; if iffuncptr(FOnPaint) then call(FOnPaint,self(true)); end function ControlAppended(AControl);override; begin if AControl is class(tcustomsplitter) then begin fhassplitter++; end end function ControlDeleted(AControl);override; begin if AControl is class(tcustomsplitter) then begin fhassplitter--; end end public function Create(AOwner:TComponent);override; begin inherited; //FCanvas := new tcanvas(); end function AfterConstruction();override; begin inherited; includestate(FControlState,csCustomPaint); fhassplitter := 0; fsplitterwilldrag := true; end function CreateParams(p);override; begin inherited; //p.style .|= WS_CLIPSIBLINGS .| WS_CLIPCHILDREN; end function Recycling();override; begin FOnPaint := nil; fsplitercache := array(); fsplitterdragimglist := nil; inherited; end function DoVScroll(o,e);virtual; begin end function DoHScroll(o,e);virtual; begin end public function WMVScroll(o,e):LM_VScroll;virtual; begin return DoVScroll(o,e); end function WMHScroll(o,e):LM_HSCROLL;virtual; begin return DoHScroll(o,e); end function WMLButtonDown(o,e);override;//拖拽释放 begin if fhassplitter<1 then return inherited; if csDesigning in ComponentState then exit; case fcurspltype of alLeft,alRight: begin drgidx := 1; end alTop,alBottom: begin drgidx := 0; end else begin return inherited; end end ; if fsplitterwilldrag then begin cimgst(); fsplitterwilldrag := false; fsplitterdraging := true; nxy := clienttowindow(e.xpos,e.ypos); _wapi.ImageList_BeginDrag(fsplitterdragimglist.Handle,drgidx,12,12); _wapi.ImageList_DragEnter(self.Handle,nxy[0],nxy[1]); crect := clientrect; ps := array(clienttoscreen(crect[0],crect[1]),clienttoscreen(crect[2],crect[3])); _wapi.clipcursor(ps); splitterenabled(false); return ; end //end inherited; end function WMLBUTTONUP(o,e);override;//拖拽实现 begin if fhassplitter<1 then return inherited; if csDesigning in ComponentState then return ; if fsplitterdraging then begin cimgst(); _wapi.ImageList_DragLeave(self.Handle); _wapi.ImageList_EndDrag(); splitterenabled(true); fsplitterwilldrag := true; fsplitterdraging := false; sizeprive(e.pos); _wapi.clipcursor(0); return ; end return inherited; end function WMMouseMove(o,e);override; //移动 begin if fhassplitter<1 then return inherited; if csDesigning in ComponentState then return inherited; if fsplitterdraging then begin cimgst(); nxy := clienttowindow(e.xpos,e.ypos); _wapi.ImageList_DragMove(nxy[0],nxy[1]); return ; end else begin xy := e.pos(); fcurspltype := nil; fcursplitterid := -1; fcursplitter := nil; for i,v in Controls.data do begin if (v is class(tcustomsplitter)) and (v.Visible) and (v.enabled) and pointinrect(xy,v.BoundsRect) and (v<>fcursplitter) then //拖拽 begin va := v.Align; if va in array(alLeft,alRight) then begin cursor := OCR_SIZEWE; fcurspltype := va; fcursplitter := v; fcursplitterid := i; return ; end else if va in array(alTop,alBottom) then begin cursor := OCR_SIZENS; fcurspltype := va; fcursplitter := v; fcursplitterid := i; return ; end end end cursor := OCR_NORMAL; end return inherited; end property OnPaint:eventhandler read FOnPaint write FOnPaint; {** @param(OnPaint)(function[TCustomControl,tuieventbase]) 窗口关闭消息回调 %% **} private function getzybmp(); begin r :="0502000000060400000074797065000203000000696D670006040000006461746 10002E300000089504E470D0A1A0A0000000D4948445200000018000000180806 000000E0773DF8000000017352474200AECE1CE90000000467414D410000B18F0 BFC6105000000097048597300000EC300000EC301C76FA8640000007849444154 484BED8FED09C0200C443B90C3B89CDB65174BC02B54134FA41F7FF220207AB98 7477D9910504240F94F2022EDC499654D812EE49C97242C3B08B0504A69371CCD 7A929B60A71C78924B80F294923BC07AC3F492EF7E0076245EB932081448AC851 E963505CA4A3998655DC1538480120242AD27B102A52F60A469C4000000004945 4E44AE42608200"; return r; end function getsxbmp(); begin r := "0502000000060400000074797065000203000000696D670006040000006461746 100027801000089504E470D0A1A0A0000000D4948445200000018000000180806 000000E0773DF8000000017352474200AECE1CE90000000467414D410000B18F0 BFC6105000000097048597300000EC300000EC301C76FA8640000010D49444154 484BE5963D0A84400C853D8885BD585AD8D97802B11704AFA19D8D78053BAFE10 5AC0541F006361E204B86380CAC6322EC6EB31F04740CEF61327F0E08699A0682 2000C771A02C4B98E799BEDC2332288A42099B118621ECFB4E19765883BAAEDFC 4CF48D394B2ECB006499228B1388EB5705555FA79DB36CABC4654A2B66D615916 2D3A8E23F47DAF8243DC64C43490F26706BEEF2B83755D6984E79101CE986118E 84D8636388E43FDFA27629A2652350CA228D235FE44E05A417E67F0F5127D8B47 06B81F799EC7EE3F268F0CCEFA6219A4FC8101AE5CDB766DCE161BAC419EE74AF 4EAC0C18673B0067747669665946547D483AB435F228E889B7C5E5B5CD785AEEB 689403E005E8019174FBC7C7A70000000049454E44AE42608200"; return r; end function candosplitter(v); begin return (not(v is class(tcustomsplitter)) and (v.Visible) and (v.Align = fcurspltype)); end function sizeprive(xy); begin id := fcursplitterid; ctls := Controls; rc := clientrect; x := max(rc[0],xy[0]); x := min(rc[2],x); y := max(rc[1],xy[1]); y:= min(rc[3],y); case fcurspltype of alLeft : begin for i:= id-1 downto 0 do begin v := ctls[i]; if candosplitter(v) then begin vL := v.Left; sw := fcursplitter.Width; nvl := max(x-vl-sw,sw); v.Align := alNone; v.Width := nvl; v.Align := fcurspltype; return ; end end end alTop: begin for i:= id-1 downto 0 do begin v := ctls[i]; if candosplitter(v) then begin vL := v.top; sw := fcursplitter.Height; nvl := max(y-vl-sw,sw); v.Align := alNone; v.Height := nvl; v.Align := fcurspltype; return ; end end end alRight: begin for i:= id-1 downto 0 do begin v := ctls[i]; if candosplitter(v) then begin vl := (v.BoundsRect)[2]; sw := fcursplitter.Width; nvl := max(vl-x-sw*1.5,sw); v.Align := alNone; v.Width := nvl; v.Align := fcurspltype; return ; end end end alBottom: begin for i:= id-1 downto 0 do begin v := ctls[i]; if candosplitter(v) then begin vL := (v.BoundsRect)[3]; sw := fcursplitter.Height; nvl := max(vl-y-sw*1.5,sw); v.Align := alNone; v.Height := nvl; v.Align := fcurspltype; return ; end end end end end function cimgst(); begin if not fsplitterdragimglist then begin fsplitterdragimglist := new TCustomImageList(self); fsplitterdragimglist.Width := 24; fsplitterdragimglist.Height := 24; bmp := new TcustomBitmap(); bmp.readvcon(HexFormatStrToTsl(getsxbmp())); fsplitterdragimglist.addbmp(bmp); bmp := new TcustomBitmap(); bmp.readvcon(HexFormatStrToTsl(getzybmp())); fsplitterdragimglist.addbmp(bmp); end end function splitterenabled(b); begin if not b then begin fsplitercache := array(); for i,v in controls.data do begin fsplitercache[i] := array(v,v.enabled); v.enabled := false; end end else begin for i,v in fsplitercache do begin v[0].enabled := v[1]; end fsplitercache := nil; end end fsplitterdragimglist; fsplitterwilldrag; fsplitterdraging; fcurspltype; fcursplitter; fcursplitterid; fsplitercache; fhassplitter; end;