unit sr_frame; interface uses windows; procedure CreateFrame(parent:HWND); procedure DestroyFrame; implementation uses commctrl,Messages,m_api,common,wrapper,mirutils,sr_global; {.$include resource.inc} const frm_back:pAnsiChar = 'Frame background'; const FrameWnd:HWND = 0; FrameId:integer = -1; OldEditProc:pointer=nil; pattern:pWideChar=nil; current: THANDLE = 0; var colorhook:THANDLE; hbr:HBRUSH; frm_bkg:TCOLORREF; function CheckContact(wnd:HWND; hContact:THANDLE):THANDLE; var buf:array [0..127] of WideChar; begin result:=0; SendMessage(wnd,CLM_GETITEMTEXT,hContact,lparam(@buf)); if StrPosW(CharLowerW(@buf),pattern)<>nil then result:=hContact; end; function GetNextContact(wnd:HWND; root,hContact:THANDLE; direction,skip:integer):THANDLE; var tmp:THANDLE; // buf:array [0..127] of WideChar; begin result:=0; repeat if skip=0 then begin case SendMessage(wnd,CLM_GETITEMTYPE,hContact,0) of CLCIT_GROUP: begin if SendMessage(wnd,CLM_GETEXPAND,hContact,0)=CLE_EXPAND then // expanded only begin tmp:=SendMessage(wnd,CLM_GETNEXTITEM,CLGN_CHILD,hContact); if tmp<>0 then begin hContact:=tmp; if direction=CLGN_PREVIOUS then begin // set on last contact in group repeat tmp:=SendMessage(wnd,CLM_GETNEXTITEM,CLGN_NEXT,hContact); if tmp<>0 then hContact:=tmp else break; until false; end; continue; end; end; end; CLCIT_CONTACT: begin result:=CheckContact(wnd,hContact); if result<>0 then break; end; else // CLCIT_INVALID for example break; end; end else skip:=0; if hContact=HCONTACT_ISGROUP then // if (hContact=root) and (direction=CLGN_PREVIOUS) then // 1st group, no need to process "root=clist" break; tmp:=SendMessage(wnd,CLM_GETNEXTITEM,direction,hContact); if tmp=0 then begin hContact:=SendMessage(wnd,CLM_GETNEXTITEM,CLGN_PARENT,hContact); // not here but where group insert skip:=1; continue; // hContact:=SendMessage(wnd,CLM_GETNEXTITEM,direction,hContact); if hContact=0 then break; end else hContact:=tmp; until false; end; function SearchContact(direction:integer;skip:integer=1):integer; var root,hContact:THANDLE; wnd:HWND; begin result:=0; if (pattern=nil) or (pattern^=#0) then begin current:=0; // next seach - from start exit; // pattern empty end; wnd:=CallService(MS_CLUI_GETHWNDTREE,0,0); root:=SendMessage(wnd,CLM_GETNEXTITEM,CLGN_ROOT,0); if current=0 then hContact:=root else hContact:=current; result:=GetNextContact(wnd,root,hContact,direction,skip); if result<>0 then SetCListSelContact(result); end; function NewEditProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; begin // result:=0; case hMessage of WM_CHAR: if wParam=27 then begin // clear edit field SendMessage(Dialog,WM_SETTEXT,0,0); // go to top? current:=0; end; WM_KEYDOWN: begin case wParam of VK_PRIOR,VK_UP: begin current:=SearchContact(CLGN_PREVIOUS); end; VK_NEXT,VK_DOWN: begin current:=SearchContact(CLGN_NEXT); end; end; end; end; result:=CallWindowProc(OldEditProc,Dialog,hMessage,wParam,lParam); end; function QSDlgResizer(Dialog:HWND;lParam:LPARAM;urc:PUTILRESIZECONTROL):int; cdecl; begin case urc^.wId of IDC_FRAME_OPEN: result:=RD_ANCHORX_LEFT or RD_ANCHORY_CENTRE; IDC_FRAME_EDIT: result:=RD_ANCHORX_WIDTH or RD_ANCHORY_CENTRE; IDC_FRAME_PREV: result:=RD_ANCHORX_RIGHT or RD_ANCHORY_CENTRE; IDC_FRAME_NEXT: result:=RD_ANCHORX_RIGHT or RD_ANCHORY_CENTRE; else result:=0; end; end; function QSFrameProc(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; var urd:TUTILRESIZEDIALOG; tmp:THANDLE; rc:TRECT; ti:TTOOLINFOW; hwndTooltip:HWND; begin result:=0; case hMessage of WM_DESTROY: begin DeleteObject(hbr); end; WM_INITDIALOG: begin OldEditProc:=pointer(SetWindowLongPtrW(GetDlgItem(Dialog,IDC_FRAME_EDIT), GWL_WNDPROC,LONG_PTR(@NewEditProc))); hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), Dialog,0,hInstance,nil); FillChar(ti,SizeOf(ti),0); ti.cbSize :=sizeof(TOOLINFO); ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; ti.hwnd :=Dialog; ti.hinst :=hInstance; ti.uId :=GetDlgItem(Dialog,IDC_FRAME_PREV); ti.lpszText:=pWideChar(TranslateW('Previous item')); SendMessage(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); ti.uId :=GetDlgItem(Dialog,IDC_FRAME_NEXT); ti.lpszText:=pWideChar(TranslateW('Next item')); SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); ti.uId :=GetDlgItem(Dialog,IDC_FRAME_OPEN); ti.lpszText:=pWideChar(TranslateW('Open main window')); SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,tlparam(@ti)); end; WM_SIZE: begin FillChar(urd,SizeOf(TUTILRESIZEDIALOG),0); urd.cbSize :=SizeOf(urd); urd.hwndDlg :=Dialog; urd.hInstance :=hInstance; urd.lpTemplate:=MAKEINTRESOURCEA(IDD_FRAME); urd.lParam :=0; urd.pfnResizer:=@QSDlgResizer; CallService(MS_UTILS_RESIZEDIALOG,0,tlparam(@urd)); end; WM_ERASEBKGND: begin GetClientRect(Dialog,rc); FillRect(wParam,rc,hbr); result:=1; end; WM_COMMAND: begin case wParam shr 16 of EN_CHANGE: begin mFreeMem(pattern); pattern:=GetDlgText(Dialog,IDC_FRAME_EDIT); if pattern<>nil then CharLowerW(pattern); tmp:=SearchContact(CLGN_NEXT,0); if tmp=0 then tmp:=SearchContact(CLGN_PREVIOUS,0); current:=tmp; end; BN_CLICKED: begin tmp:=0; case loword(wParam) of IDC_FRAME_PREV: tmp:=SearchContact(CLGN_PREVIOUS); IDC_FRAME_NEXT: tmp:=SearchContact(CLGN_NEXT); IDC_FRAME_OPEN: CallService(QS_SHOWSERVICE,twparam(pattern),0); end; if tmp<>0 then current:=tmp; end; end; end; else result:=DefWindowProc(Dialog,hMessage,wParam,lParam); end; end; function ColorReload(wParam:WPARAM;lParam:LPARAM):int;cdecl; var cid:TColourID; begin result:=0; cid.cbSize:=SizeOf(cid); StrCopy(cid.group,'QuickSearch'); StrCopy(cid.name ,frm_back); frm_bkg:=CallService(MS_COLOUR_GETA,twparam(@cid),0); DeleteObject(hbr); hbr:=CreateSolidBrush(frm_bkg); RedrawWindow(FrameWnd,nil,0,RDW_ERASE); end; procedure CreateFrame(parent:HWND); var Frame:TCLISTFrame; wnd:HWND; tmp:cardinal; tr:TRECT; cid:TColourID; begin if ServiceExists(MS_CLIST_FRAMES_ADDFRAME)=0 then exit; if parent=0 then parent:=CallService(MS_CLUI_GETHWND,0,0); if FrameWnd=0 then FrameWnd:=CreateDialog(hInstance,MAKEINTRESOURCE(IDD_FRAME),parent,@QSFrameProc); if FrameWnd<>0 then begin GetWindowRect(FrameWnd,tr); FillChar(Frame,SizeOf(Frame),0); with Frame do begin cbSize :=SizeOf(Frame); hWnd :=FrameWnd; hIcon :=CallService(MS_SKIN2_GETICON,0,tlparam(QS_QS)); align :=alTop; height :=tr.bottom-tr.top+2; Flags :=F_VISIBLE or F_NOBORDER or F_UNICODE; name.w :='Quick search'; TBName.w:='Quick search'; end; FrameId:=CallService(MS_CLIST_FRAMES_ADDFRAME,wparam(@Frame),0); if FrameId>=0 then begin CallService(MS_CLIST_FRAMES_UPDATEFRAME,FrameId, FU_FMPOS); wnd:=CallService(MS_CLUI_GETHWND{MS_CLUI_GETHWNDTREE},0,0); tmp:=SendMessage(wnd,CLM_GETEXSTYLE,0,0); SendMessage(wnd,CLM_SETEXSTYLE,tmp or CLS_EX_SHOWSELALWAYS,0); cid.cbSize:=SizeOf(cid); cid.flags :=0; StrCopy(cid.group,'QuickSearch'); StrCopy(cid.dbSettingsGroup,qs_module); StrCopy(cid.name ,frm_back); StrCopy(cid.setting,'frame_back'); cid.defcolour:=COLOR_3DFACE; cid.order :=0; ColourRegister(@cid); colorhook:=HookEvent(ME_COLOUR_RELOAD,@ColorReload); ColorReload(0,0); end; end; end; procedure DestroyFrame; begin if FrameId>=0 then begin UnhookEvent(colorhook); CallService(MS_CLIST_FRAMES_REMOVEFRAME,FrameId,0); FrameId:=-1; end; DestroyWindow(FrameWnd); FrameWnd:=0; mFreeMem(pattern); end; end.