为何我用C++ WinAPI做的窗口未显示

为何我用C++ WinAPI做的窗口未显示,第1张

有时候可能是编译器版本低,我也碰到这种情况,后来用keil 4 调试的时候就没有事,而且keil 4 中有反汇编模式和混合模式,混合模式就是C和反汇编窗口豆油**箭头的,而反汇编模式只在反汇编窗口里有箭头。其他也有可能是你的程序问题,使程序没有跳到入口地址(main)。

SetForegroundWindow 函数功能:该函数将创建指定窗口的线程设置到前台,并且激活该窗口。键盘输入转向该窗口,并为用户改各种可视的记号。系统给创建前台窗口的线程分配的权限稍高于其他线程。

函数原型:BOOL SetForegroundWindow()

SetForegroundWindow()函数本身是不带参数的,具体激活某个窗口的方法可以用:

pWnd->SetForegroundWindow();//这里的pWnd即所要激活窗口的句柄。

返回值:如果窗口设入了前台,返回值为非零;如果窗口未被设入前台,返回值为零。

备注:前台窗口是z序顶部的窗口,是用户的工作窗口。在一个多任务优先抢占环境中,应让用户控制前台窗口。

Windows NT 50:当用户在另一个窗口中工作时,应用程序不能强行设置一个窗口到前台。相反,SetForeground函数将会激活窗口并且调用FlashWindowEx函数通知用户。

Windows CE:拥有窗口的线程不具有优先启动权。

速查:Windows NT;31以上版本;Windows;95以上版本;Windows CE:10以上版本;头文件:winuserh;库文件:user32lib。

SetWindowPlacement 函数功能:该函数设置指定窗口的显示状态和恢复,最大化,最小化位置。

函及原型;BOOL SetWindowPlacement(HWND hWnd,CONST WINDOWPLACEMENT★lpwndpl);

参数:

hWnd:窗口句柄。

lpwndpl:指向一个WINDOWPLACEMWNT结构的指针,该结构给出了新的显示状态和窗口位置。

在调用函数SetWindowPlacement之前,将WINDOWPLACEMWNT结构的长度单元置为sizeof(WINDOWPLACEMENT)。如果lpwndpl->length设置不正确,函数SetWindowPlacement将失败。

返回值:如果函数成功,返回值为非零。如果函数失败,返回值为零。若想获得更多错误信息,请调用callGetLastErro函数。

备注:如果在WIDNOWPLACEMENT中指定的信息使窗口完全显示在屏幕之外,系统自动调整坐标以使窗口可见,兼顾屏幕设置和多种监视器配置。

WINDOWPLACEMENT的长度成员信息设置为sizeof(WINDOWPLACEMENT),如果设置不正确,函数将返回FLASE。查看窗口位置坐标的信息,参看WINDOWPLACEMENT。

速查:Windows NT:31以上版本;Windows;95以上版本;Windows CE:不支持;头文件;winuserh;库文件:user32lib。

SetForegroundWindow()

SetActiveWindow()

SetFocus()

自己的理解:每个gui线程都有自己的活动窗口,而目前被用户点中那个线程活动窗口叫前台窗口(或叫前景窗口)。而创建前台窗口的线程叫做前台线程(或叫前景线程),前台线程拥有比其它非前景线程更高的优先级,会被windows *** 作系统优先处理。而所谓的焦点窗口,可以是前台窗口或者是前台窗口的子窗口(控件),如果用户按下键盘按键,windows *** 作系统会将键盘按键消息发送到当前的焦点窗口。

-------------------------------------

如何将一个某个窗口提到最顶层网上搜索了一些文章大致有以下几种方法,做个备忘

问题:有个界面,想定期让其提前(并显示在用户面前),但又不想用TOPMOST那种置顶方法我用了SetForegroundWindow,SetActiveWindow,SHOW_WINDOW都不行:程序运行后再打开记事本,时间到我的程序只会在任务栏上闪几下,界面根本出不来怎么办!!(不用顶极窗口,不用鼠标模拟点击)

方法一:

使用定时器,然后在定时器响应函数中定时调用,SetWindowPos()函数,第一个参数写HWND_TOPMOST

方法二:

因为2000/XP改变了SetForegroundWindow的执行方式,不允许随便把窗口提前,打扰用户的工作。可以用附加本线程到最前面窗口的线程,从而欺骗windows。

AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow(),NULL), GetCurrentThreadId(),TRUE);

SetForegroundWindow();

SetFocus();

AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow(),NULL), GetCurrentThreadId(),FALSE);

方法三:

如何激活指定的窗口事件 ●

我们知道,Windows 9x/2000中SetForegroundWindow函数当用户正在 *** 作其他窗口时是不能强制某个窗口为前景窗口的,而是激活窗口并调用FlashWindowEx函数来通知用户。但是很多实际情况要求将激活窗口的同时将创建这个窗口的线程置为前景状态。碰到这种情况我们可以使用USER32DLL中的几个未公开API函数。

void SwitchToThisWindow (

HWND hWnd, // 被激活的窗口句柄

BOOL bRestore // 如果被极小化,则恢复窗口

);

必须动态加载这个函数。

typedef void (WINAPI PROCSWITCHTOTHISWINDOW) (HWND, BOOL);

PROCSWITCHTOTHISWINDOW SwitchToThisWindow;

HMODULE hUser32 = GetModuleHandle("user32");

SwitchToThisWindow = ( PROCSWITCHTOTHISWINDOW)

GetProcAddress(hUser32, "SwitchToThisWindow");

接下来只要用任何现存窗口的句柄调用这个函数即可,第二个参数指定如果窗口极小化,是否恢复其原状态。

SwitchToThisWindow(hWnd, TRUE);

1、简单的说可以在OnInitDialog()函数里加上一句:

RECT rect;

GetClientRect(&rect);

MoveWindow(1024-rectright,0,rectright,rectbottom);

以上MoveWindow中的前两个参数就是窗体显示时的左上角坐标,

假设你的屏幕分辨率为1024768,所以其横坐标为1024-rectright;

2、例程:

#include <windowsh>

HWND HMainwnd = NULL; //窗体句柄

int run(); //消息循环函数

bool InitWindowsApp(HINSTANCE instanceHandle, int show); //窗体初始化函数

LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp);//窗体处理回调函数

//main函数

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )

{

if(!InitWindowsApp(hInstance, nShowCmd))//判断窗体初始化是否成功

{

return 0;

}

run(); //初始化成功后循环接收消息

return 0;

}

bool InitWindowsApp(HINSTANCE stanceHandle, int show)

{

WNDCLASS wc; //窗体类结构体

wcstyle = CS_HREDRAW | CS_VREDRAW; //窗体风格

wclpfnWndProc = WndProc; //窗体处理函数

wccbClsExtra = 0; //窗体类是否由扩展

wccbWndExtra = 0; //窗体实例是否由扩展

wchInstance = stanceHandle; //窗体句柄

wchIcon = LoadIcon(0, IDI_APPLICATION); //窗体图标

wchCursor = LoadCursor(NULL, IDC_ARROW); //窗体鼠标样式

wchbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //窗体背景颜色

wclpszMenuName = NULL; //窗体菜单

wclpszClassName = "BaseWndClass"; //窗体类名

if(!RegisterClass(&wc)) //判断窗体是否注册成功

{

MessageBox(0, "注册失败", 0, 0);

return false;

}

//创建窗体

HMainwnd = CreateWindow("BaseWndClass", //窗体类名

"MyFrom", //窗体标题名

WS_OVERLAPPEDWINDOW, //窗体风格

CW_USEDEFAULT,

CW_USEDEFAULT, //窗体坐标

CW_USEDEFAULT,

CW_USEDEFAULT, //窗体坐标

NULL, //窗体的父窗体

NULL, //窗体的子菜单

stanceHandle, //窗体句柄

NULL); // 如果函数成功,返回值为新窗口的句柄:如果函数失败,返回值为NULL

if(HMainwnd == 0)//判断创建窗体是否成功

{

MessageBox(0, "创建窗体失败", 0, 0);

return false;

}

ShowWindow(HMainwnd, SW_SHOW); //显示窗体

UpdateWindow(HMainwnd); //绘制窗体;

return true;

}

LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wp, LPARAM lp)

{

switch(msg)//判断消息的种类

{

case WM_LBUTTONDOWN: //左键单击

MessageBox(0, "Hello World", "myMbox", MB_OK);

return 0;

case WM_KEYDOWN: //键盘消息

if(wp == VK_ESCAPE) //ESC键

DestroyWindow(HMainwnd); //销毁窗体

return 0;

case WM_DESTROY:

PostQuitMessage(0); //终止消息

return 0;

}

return DefWindowProc(wnd, msg, wp, lp); //返回缺省消息函数

}

int run()

{

MSG msg = {0}; //消息结构

BOOL bRet = 1; //获取消息

while( (bRet = GetMessage(&msg, 0, 0, 0)) != 0)//消息循环

{

if(bRet == -1)//判断消息是否接收失败

{

MessageBox(0, "接受消息失败", 0, 0);

break;

}

else

{

TranslateMessage(&msg); //转换消息为字符消息

DispatchMessage(&msg); //发送消息给窗口

}

}

return (int)msgwParam;

}

函数功能:

CreateWindow 函数创建一个重叠式窗口、d出式窗口或子窗口。它指定窗口类,窗口标题,窗口风格,以及窗口的初始位置及大小(可选的)。函数也指该窗口的父窗口或所属窗口(如果存在的话),及窗口的菜单。

若要使用除 CreateWindow 函数支持的风格外的扩展风格,则使用 CreateWindowEx 函数代替 CreateWindow 函数。

API 函数原型:

注释:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数。

HWND WINAPI CreateWindow(

_In_opt_  LPCTSTR lpClassName,    // 窗口类名称

_In_opt_  LPCTSTR lpWindowName,   // 窗口标题

_In_      DWORD dwStyle,          // 窗口风格,或称窗口格式

_In_      int x,                  // 初始 x 坐标

_In_      int y,                  // 初始 y 坐标

_In_      int nWidth,             // 初始 x 方向尺寸

_In_      int nHeight,            // 初始 y 方向尺寸

_In_opt_  HWND hWndParent,        // 父窗口句柄

_In_opt_  HMENU hMenu,            // 窗口菜单句柄

_In_opt_  HINSTANCE hInstance,    // 程序实例句柄

_In_opt_  LPVOID lpParam          // 创建参数

);

参数解析:

参数 含义

lpClassName

1 窗口类名称,可以是一个指向 NULL 结束的字符串或一个整型数值

2 如果是字符串,它指定了窗口的类名。这个类名可以是任何用函数 RegisterClass 注册的类名,或是任何预定义的控制类名

3 如是一个整型量,它是由此前调用 theGlobalAddAtom 函数产生的全局量。这个小于 0xC000 的 16 位数必须是 lpClassName 参数字的低 16 位,该参数的高位必须是 0

lpWindowName

1 窗口标题,一个指向 NULL 结束的字符串指针

2 如果窗口风格指定了标题条,由 lpWindowName 指向的窗口标题将显示在标题条上

3 当使用 Createwindow 函数来创建控制例如按钮,选择框和静态控制时,可使用 lpWindowName 来指定控制文本

dwStyle

指定创建窗口的风格(详见下方↓)

x:1 指定窗口的初始水平位置(x 坐标)

2 对一个层叠或d出式窗口,x 参数是屏幕坐标系的窗口的左上角的初始 x 坐标

3 对于子窗口,x 是子窗口左上角相对父窗口客户区左上角的初始 x 坐标

4 如果该参数被设为 CW_USEDEFAULT 则系统为窗口选择缺省的左上角坐标并忽略 y 参数,CW_USEDEFAULT 只对层叠窗口有效,如果为d出式窗口或子窗口设定,则 x 和 y 参数被设为零。

y:1 指定窗口的初始垂直位置(y 坐标)

2 对一个层叠或d出式窗口,y 参数是屏幕坐标系的窗口的左上角的初始 y 坐标

3 对于子窗口,y 是子窗口左上角相对父窗口客户区左上角的初始 y 坐标

4 对于列表框,y 是列表框客户区左上角相对父窗口客户区左上角的初始 y 坐标

5 如果层叠窗口是使用 WS_VISIBLE 风格位创建的并且 x 参数被设为 CW_USEDEFAULT,则系统将忽略 y 参数

nWidth1 以设备单元指明窗口的宽度

2 对于层叠窗口,nWidth 的值或是屏幕坐标的窗口宽度或是 CW_USEDEFAULT

3 若 nWidth 是 CW_USEDEFAULT,则系统为窗口选择一个默认的高度和宽度(默认宽度为从初始 x 坐标开始到屏幕的右边界,缺省高度为从初始 y 坐标开始到目标区域的顶部。),CW_USEDEFAULT 只对层叠窗口有效,如果为d出式窗口和子窗口设定 CW_USEDEFAULT 标志则 nWidth 和 nHeight 被设为零

nHeight1 以设备单元指明窗口的高度

2 对于层叠窗口,nHeight 是屏幕坐标的窗口宽度

3 若 nWidth 被设为 CW_USEDEFAULT,则系统忽略 nHeight 参数,自动为 nWidth 和 nHeight 设置默认参数

hWndParent

1 指向被创建窗口的父窗口或所有者窗口的句柄

2 若要创建一个子窗口或一个从属窗口,需提供一个有效的窗口句柄

3 创建一个单纯的消息窗口,可以提供 HWND_MESSAGE 或提供一个己存在的消息窗口的句柄

hMenu

1 指向窗口菜单句柄,或依据窗口风格指明一个子窗口标识

2 对于层叠或d出式窗口,hMenu 指定窗口使用的菜单:如果使用了菜单类,则 hMenu 可以为 NULL

3 对于子窗口,hMenu 指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的

hInstance与窗口相关联的模块实例的句柄

lpParam

1 指向一个值的指针,该值传递给窗口 WM_CREATE 消息。该值通过在 IParam 参数中的 CREATESTRUCT 结构传递

2 如果应用程序调用 CreateWindow 创建一个 MDI 客户窗口,则 lpParam 必须指向一个 CLIENTCREATESTRUCT 结构

dwStyle 窗口风格解析

窗口风格 含义

WS_BORDER创建一个带边框的窗口

WS_CAPTION创建一个有标题框的窗口(包含了 WS_BODER 风格)

WS_CHILD创建一个子窗口,这个风格的窗口不能拥有菜单也不能与 WS_POPUP 风格合用

WS_CHILDWINDOW与 WS_CHILD 相同

WS_CLIPCHILDREN当在父窗口内绘图时,排除子窗口区域,在创建父窗口时使用这个风格

WS_CLIPSIBLINGS1 排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到 WM_PAINT 消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口

2 如果未指定该风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口

WS_DISABLED1 创建一个初始状态为禁止的子窗口,一个禁止状态的窗口不能接受来自用户的输入信息

2 在窗口创建之后,可以调用 EnableWindow 函数来启用该窗口

WS_DLGFRAME创建一个带对话框边框风格的窗口,这种风格的窗口不能带标题条

WS_GROUP1 指定一组“控制窗口”的第一个“控制窗口”

2 这个“控制窗口”组由第一个“控制窗口”和随后定义的“控制窗口”组成,自第二个“控制窗口”开始每个“控制窗口”具有 WS_GROUP 风格

3 每个组的第一个“控制窗口”带有 WS_TABSTOP 风格,从而使用户可以在组间移动

4 用户随后可以使用光标在组内的控制间改变键盘焦点

WS_HSCROLL创建一个有水平滚动条的窗口

WS_ICONIC创建一个初始状态为最小化状态的窗口,与 WS_MINIMIZE 风格相同

WS_MAXIMIZE创建一个初始状态为最大化状态的窗口

WS_MAXIMIZEBOX创建一个具有最大化按钮的窗口,该风格不能与 WS_EX_CONTEXTHELP 风格同时出现,同时必须指定 WS_SYSMENU 风格

WS_MINIMIZE创建一个初始状态为最小化状态的窗口,与 WS_ICONIC 风格相同

WS_MINIMIZEBOX创建一个具有最小化按钮的窗口,该风格不能与 WS_EX_CONTEXTHELP 风格同时出现,同时必须指定 WS_SYSMENU 风格

WS_OVERLAPPED产生一个层叠的窗口,一个层叠的窗口有一个标题条和一个边框,与 WS_TILED 风格相同

WS_OVERLAPPEDWINDOW相当于(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX),与 WS_TILEDWINDOW 风格相同

WS_POPUP创建一个d出式窗口,该风格不能与 WS_CHILD 风格同时使用。

WS_POPUPWINDOW相当于(WS_POPUP | WS_BORDER | WS_SYSMENU),但 WS_CAPTION 和 WS_POPUPWINDOW 必须同时设定才能使窗口某单可见

WS_SIZEBOX创建一个可调边框的窗口,与 WS_THICKFRAME 风格相同

WS_SYSMENU创建一个在标题条上带有窗口菜单的窗口,必须同时设定 WS_CAPTION 风格

WS_TABSTOP1 创建一个“控制窗口”,在用户按下 Tab 键时可以获得键盘焦点。

2 按下 Tab 键后使键盘焦点转移到下一具有 WS_TABSTOP 风格的“控制窗口”

WS_THICKFRAME创建一个具有可调边框的窗口,与 WS_SIZEBOX 风格相同

WS_TILED产生一个层叠的窗口,一个层叠的窗口有一个标题和一个边框,与 WS_OVERLAPPED 风格相同

WS_TILEDWINDOW相当于(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX),与 WS_OVERLAPPEDWINDOW 风格相同

WS_VISIBLE创建一个初始状态为可见的窗口

WS_VSCROLL创建一个有垂直滚动条的窗口

返回值:

1 如果函数成功,返回值为新窗口的句柄;

2 如果函数失败,返回值为 NULL。

给你一个思路吧:如果是顶级窗口类名和标题都知道的话

用api的寻找顶级窗口

找到顶级窗口句柄

之后在用

api的寻找子窗口

寻找子窗口下的标题和类名

就可以取到子窗口的句柄

之后向该句柄发送信息就行!

如果窗口是现有程序的,使用VS自带的spy++获取窗口的相关信息,然後使用WinAPI获取句柄,具体参考spy++的使用方法和winapi的使用

FindWindow(

lpClassName, {窗口的类名}

lpWindowName: PChar {窗口的标题}

): HWND; {返回窗口的句柄; 失败返回 0}

//FindWindowEx 比 FindWindow 多出两个句柄参数:

FindWindowEx(

Parent: HWND; {要查找子窗口的父窗口句柄}

Child: HWND; {子窗口句柄}

ClassName: PChar; {}

WindowName: PChar {}

): HWND;

如果窗口是你的程序动态生成的,使用如下语句

Form _FORM=new Form();

IntPtr _P = _FORMHandle;

_P就是你实例化的窗口句柄

窗口最小化后 GetWindowPlacement 只能获取到窗口的 RECT,不能获取客户区的。

WINDOWPLACEMENT wndpl;

wndpllength = sizeof(WINDOWPLACEMENT);

GetWindowPlacement(hwnd, &wndpl);

// wndplrcNormalPositionleft;

// wndplrcNormalPositiontop;

// wndplrcNormalPositionright;

// wndplrcNormalPositionbottom;

MSDN 还说:

If the window is a top-level window that does not have the WS_EX_TOOLWINDOW window style, then the coordinates represented by the following members are in workspace coordinates: ptMinPosition, ptMaxPosition, and rcNormalPosition Otherwise, these members are in screen coordinates

如果窗口是没有 WS_EX_TOOLWINDOW 窗口样式的顶级窗口,(结构体 WINDOWPLACEMENT 的)以下成员代表的坐标为工作区坐标:ptMinPosition、ptMaxPosition 和 rcNormalPosition。否则,这些成员为屏幕坐标。

工作区坐标可能是指以除去任务栏之后的 RECT 为坐标。

以上就是关于为何我用C++ WinAPI做的窗口未显示全部的内容,包括:为何我用C++ WinAPI做的窗口未显示、SetForegroundWindow以及 如何将一个某个窗口提到最顶层、VC++MFC 怎么设置初始化窗体的位置等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9488442.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存