使用windowsAPI对firefox进行多页面管理

 最近因为项目上的需要对系统的部分数据展示页面使用web页面来进行开发,web页面在做展示的需要像对话框一样,可以弹出来的时候置顶到桌面第一个窗口,可以自定义每一个窗口的大小。浏览器使用了第三方公司封装的firefox浏览器,屏蔽了地址栏和收藏夹栏,所以看起来跟对话框是一模一样的。正好在看windows核心编程,趁着这个项目练练手,熟悉熟悉windows API。

在创建firefox进程的时候使用如下接口:

BOOL WINAPI CreateProcess(
  _In_opt_    LPCTSTR               lpApplicationName,
  _Inout_opt_ LPTSTR                lpCommandLine,
  _In_opt_    LPSECURITY_ATTRIBUTES lpProcessAttributes,
  _In_opt_    LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_        BOOL                  bInheritHandles,
  _In_        DWORD                 dwCreationFlags,
  _In_opt_    LPVOID                lpEnvironment,
  _In_opt_    LPCTSTR               lpCurrentDirectory,
  _In_        LPSTARTUPINFO         lpStartupInfo,
  _Out_       LPPROCESS_INFORMATION lpProcessInformation
);

在LPPROCESS_INFORMATION这个结构体里面有进程被创建的信息,但是没有窗口句柄的HWND,通过窗口句柄才可以对窗口的大小,显示位置等信息进行设置,调用如下函数:

BOOL WINAPI SetWindowPos(
  _In_     HWND hWnd,
  _In_opt_ HWND hWndInsertAfter,
  _In_     int  X,
  _In_     int  Y,
  _In_     int  cx,
  _In_     int  cy,
  _In_     UINT uFlags
);

其中uFlags设为HWND_TOPMOST可以保证窗口在Z-Order的最前面。

LPPROCESS_INFORMATION结构体信息中是有processId的,我们可以使用enumwindows遍历所有的窗口通过判断两个进程号是否相等来获取窗口句柄HWND。

BOOL WINAPI EnumWindows(
  _In_ WNDENUMPROC lpEnumFunc,
  _In_ LPARAM      lParam
);

但是firefox浏览器在创建进程后是单进程的,以后的tab页面即使使用createprocess方法创建出来(有自己的processId和threadId),但是在任务管理器中它始终只是显示一个。所以上述方法是无法获取到后创建出来的tab页(或者新的窗口)的句柄。但是windows既然绘制出了这个页面,那么它肯定是有句柄的,所以现在就是要想办法获取到这个HWND。

这里还是使用上述的enumwindows方法,但是需要修改一下lpEnumFunc方法,因为界面都是我创建出来的,所以我知道每一个窗口的标题是什么,在遍历所有的窗口的时候,使用getwindowtext来获取当前遍历的HWND的标题

int WINAPI GetWindowText(
  _In_  HWND   hWnd,
  _Out_ LPTSTR lpString,
  _In_  int    nMaxCount
);

使用GetWindowThreadProcessId获取hwnd的进程号:

DWORD WINAPI GetWindowThreadProcessId(
  _In_      HWND    hWnd,
  _Out_opt_ LPDWORD lpdwProcessId
);

比对它的标题和进程号是否与firefox的进程号以及我们传入的浏览器标题参数是否一致,这样就能获得相应的窗口的HWND了。

在现场部署的时候发生了另一个问题,现场存在另一个厂家,他们也是用firefox浏览器来做数据展示,当然不是我们的定制版,因为我们还使用到了npapi插件,所以存在别人如果先打开了他们的浏览器,再通过我的接口打开我的浏览器,我的窗口界面确实会打开,但是是通过别人的浏览器执行体来创建的,即使我在使用createprocess方法的时候明确写入了自己的执行体路径和配置文件路径。lpCommandLine的参数如下:

-no -profile %配置文件路径 -new -tab

这里我谷歌了很久,总结出来就是如何开启firefox多实例运行,最后的结论是可以这么做的,lpCommandLine的参数如下:

-no-remote -profile %配置文件路径 -new -tab

确实可以按照设定的执行体路径打开一个firefox新的实例,但是问题是需要再打开一个页面的时候就会报错,因为使用“-no-remote”参数会lock住当前的配置文件,而我的插件是在profile中的,这就代表我每开一个新的页面需要重新指定一个profile路径,每个profile大小大概是70m左右。

暂时没想到有什么好的解决方案。

待续。

猜你喜欢

转载自www.cnblogs.com/masterWuGUI/p/8964223.html