打印本文 打印本文 关闭窗口 关闭窗口
Window SubClassing另类运用(之二)
作者:武汉SEO闵涛  文章来源:敏韬网  点击数3714  更新时间:2009/4/23 18:39:46  文章录入:mintao  责任编辑:mintao
  Found := False;


  while IsWindow(wnd) do begin


    GetClassName(wnd, ClassName, 80);


    if lstrcmpi(ClassName, ''''SysTreeView32'''')=0 then begin


       Found := True;


       Break;


    end;


    wnd := GetWindow(wnd, GW_HWNDNEXT);


  end;


  if not Found then Exit;


为了能够让插入的ComboBox和其他窗口控件的布局协调一致,首先需要找到用来显示文件夹的TreeView窗口。我的计划是:让ComboBox占据TreeView原来的位置(当然它的高度要比TreeView小得多),然后,包括TreeView在内的其他窗口依次下移。下面是实现代码:


  // Add combo Box and move other controls down


  GetWindowRect(wnd, rc);


  ScreenToClient(AWnd, rc.TopLeft);


  ScreenToClient(AWnd, rc.BottomRight);


  wndCombo := CreateWindow(''''COMBOBOX'''', '''''''',


                         WS_CHILD or WS_VISIBLE or CBS_DROPDOWNLIST or CBS_OWNERDRAWFIXED or CBS_HASSTRINGS,


                         rc.Left, rc.Top,


                         rc.Right-rc.Left, rc.Bottom-rc.Top,


                         AWnd, HMENU(IDC_COMBO),


                         HInstance, nil);


  SendMessage(wndCombo, WM_SETFONT,


              SendMessage(AWnd, WM_GETFONT, 0, 0),


              1);


  OldStyle := GetWindowLong(wnd, GWL_STYLE);


  SetWindowLong(wnd, GWL_STYLE, OldStyle or TVS_SHOWSELALWAYS);


 


  SaveRect := rc;


  wnd := GetWindow(AWnd, GW_CHILD);


  while IsWindow(wnd) do begin


    GetWindowRect(wnd, rc);


    ScreenToClient(AWnd, rc.TopLeft);


    ScreenToClient(AWnd, rc.BottomRight);


    if (wnd<>wndCombo) and (rc.Top>=SaveRect.Top) then


       SetWindowPos(wnd, HWND_NOTOPMOST, rc.Left, rc.Top+40, 0, 0, SWP_NOSIZE or SWP_NOZORDER);


    wnd := GetWindow(wnd, GW_HWNDNEXT);


  end;


  GetWindowRect(AWnd, rc);


  SetWindowPos(AWnd, HWND_NOTOPMOST, 0, 0, rc.Right-rc.Left, rc.Bottom-rc.Top+40, SWP_NOMOVE or SWP_NOZORDER);


 


如果你过去很少用API写程序,那么这些代码可能让你看得有点头晕。基本上上述程序完成如下的工作:


(1)计算TreeView在窗口中的位置;


(2)建立ComboBox窗口,并基于TreeView的位置将它放置到合理的地方;


(3)将ComboBox的字体设置为和整个窗体的字体相同(这一步是必要的,否则显示的效果会很难看);


(4)为TreeView的窗口风格添加TVS_SHOWSELALWAYS位,从而在焦点移动到ComboBox的时候,仍然可以明显的观察到TreeView中究竟选中了哪个项目;


(5)将窗口中的其他控件依次下移,从而为ComboBox腾出必要的空间;


(6)将窗口本身的高度也略微放大,从而适应添加ComboBox以后的大小。


 


下一步就是向ComboBox中增加一些表项,否则的话它就是一个鸡肋。我决定添加两种项目:(1)系统中的某些特殊路径,这些路径可以通过SHGetSpecialFolderLocation获得;(2)通常的文件路径。为了让代码简洁一些,我增加了一个辅助函数:


 


  procedure InsertComboItem(hCombo:HWND; const Text:string; data:DWORD);


  var


    nIndex : integer;


  begin


    nIndex := SendMessage(hCombo, CB_ADDSTRING, 0, LongInt(PChar(Text)));


    SendMessage(hCombo, CB_SETITEMDATA, nIndex, data);


  end;


 


然后在AdjustDlg函数的末尾添加如下的代码:


  InsertComboItem(wndCombo, '''''''', CSIDL_DESKTOP);


  InsertComboItem(wndCombo, '''''''', CSIDL_FAVORITES);


  InsertComboItem(wndCombo, '''''''', CSIDL_STARTMENU);


  InsertComboItem(wndCombo, '''''''', CSIDL_DRIVES);


  InsertComboItem(wndCombo, ''''c:\'''', 555);


  InsertComboItem(wndCombo, ''''d:\winnt'''', 555);


  InsertComboItem(wndCombo, ''''c:\windows\system'''', 555);


这里用555并没有什么特别的意义。我本来想用0来标志普通文件夹,但后来发现CSIDL_DESKTOP正是定义为0,所以必须用其他数字来区分。555是我信手写的,你当然可以用别的数字,只要注意不要和预定义的CSIDL常量冲突即可。


 


AdjustDlg函数的内容就这么多。接下来是NewBrowseProc函数的内容,它的基本结构如下:


function NewBrowseProc(AWnd:HWND; uMsg:UINT; wp:WPARAM; lp:LPARAM):LongInt; stdcall;


begin


  Result := 0;


case uMsg of



  end;


  if Assigned(OldBrowseProc) then


    Result := OldBrowseProc(AWnd, uMsg, wp, lp);

上一页  [1] [2] [3] [4]  下一页

打印本文 打印本文 关闭窗口 关闭窗口