win32的创建窗口

 我来答
厍河s1
2016-05-10 · TA获得超过270个赞
知道答主
回答量:189
采纳率:100%
帮助的人:64.5万
展开全部

创建一个窗口的过程如下:
取得程序的实例句柄(hInstance)
注册窗口类,实际上就是为你的窗口指定处理消息的过程,定义光标,窗口风格,颜色等参数
创建窗口
显示窗口
然后进入消息循环,也就是不停地检测有无消息,并把它发送给窗口进程去处理。 创建一个窗口的代码在不同的程序中实际上是几乎一模一样的,所以你编一个新的程序时可以把这一段拷来拷去,稍微修改一下就行,程序的大部分代码实际上是用在窗口过程中,因为这才是不同程序的不同之处。窗口过程的编程要点如下:
从Windows传给窗口过程的参数 uMsg 得到消息类型,并转到不同的分枝去处理。
对自己已经处理的消息,返回 Windows 时必须在eax 中返回0。
自己不处理的消息,必须调用 DefWindowProc 处理,并把返回值传回Windows,否则,Windows会无法显示。
uMsg 参数中指定的消息有280多种,实际上我们需要处理的只有重要的几种,如Windows在创建的时候会发送 WM_CREATE 消息,我们就可以在这时候初始化,分配内存等等,而退出时会发送 WM_CLOSE,我们就可以进行释放内存等清除工作,当Windows上的菜单或按钮被按下时发送 WM_COMMAND 消息等等,具体可以参考 Win32 Programmer's Reference。下面,我们来看一个创建窗口的简单程序。
程序
.386
.model flat, stdcall
option casemap :none ; case sensitive
include windows.inc
include user32.inc
include kernel32.inc
include comctl32.inc
include comdlg32.inc
include gdi32.inc
includelib user32.lib
includelib kernel32.lib
includelib comctl32.lib
includelib comdlg32.lib
includelib gdi32.lib
IDI_MAIN equ 1000 ;icon
IDM_MAIN equ 4000 ;menu
IDM_EXIT equ 4001
.data?
hInstance dd ?
hWinMain dd ?
hMenu dd ?
szBuffer db 256 dup (?)
.data
szClassName db Windows Template,0
szCaptionMain db '窗口模板',0
.code
start:
call _WinMain
invoke ExitProcess,NULL
_WinMain proc
local @stWcMain:WNDCLASSEX
local @stMsg:MSG
invoke InitCommonControls
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke LoadIcon,hInstance,IDI_MAIN
mov hIcon,eax
invoke LoadMenu,hInstance,IDM_MAIN
mov hMenu,eax
;*************** 注册窗口类 *****************************************
invoke LoadCursor,0,IDC_ARROW
mov @stWcMain.hCursor,eax
mov @stWcMain.cbSize,sizeof WNDCLASSEX
mov @stWcMain.hIconSm,0
mov @stWcMain.style,CS_HREDRAW or CS_VREDRAW
mov @stWcMain.lpfnWndProc,offset WndMainProc
mov @stWcMain.cbClsExtra,0
mov @stWcMain.cbWndExtra,0
mov eax,hInstance
mov @stWcMain.hInstance,eax
mov @stWcMain.hIcon,0
mov @stWcMain.hbrBackground,COLOR_WINDOW + 1
mov @stWcMain.lpszClassName,offset szClassName
mov @stWcMain.lpszMenuName,0
invoke RegisterClassEx,addr @stWcMain
;*************** 建立输出窗口 ***************************************
invoke CreateWindowEx,WS_EX_CLIENTEDGE,\
offset szClassName,offset szCaptionMain,\
WS_OVERLAPPEDWINDOW OR WS_VSCROLL OR WS_HSCROLL,\
0,0,550,300,\
NULL,hMenu,hInstance,NULL
invoke ShowWindow,hWinMain,SW_SHOWNORMAL
invoke UpdateWindow,hWinMain
;*************** 消息循环 *******************************************
.while TRUE
invoke GetMessage,addr @stMsg,NULL,0,0
.break .if eax == 0
invoke TranslateMessage,addr @stMsg
invoke DispatchMessage,addr @stMsg
.endw
ret
_WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
WndMainProc proc uses ebx edi esi, \
hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
mov eax,uMsg
.if eax == WM_CREATE
mov eax,hWnd
mov hWinMain,eax
call _Init
.elseif eax == WM_COMMAND
.if lParam == 0
mov eax,wParam
.if ax == IDM_EXIT
call _Quit
.endif
.endif
.elseif eax == WM_CLOSE
call _Quit
.else
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax,eax
ret
WndMainProc endp
_Init proc
invoke SendMessage,hWinMain,WM_SETICON,ICON_SMALL,hIcon
ret
_Init endp
_Quit proc
invoke DestroyWindow,hWinMain
invoke PostQuitMessage,NULL
ret
_Quit endp
end start
窗口程序的分析
让我们来简单分析一下这个程序,首先程序调用 _WinMain,在_WinMain 中定义了两个局部变量 @stMsg 和 @stWinMain,数据类型分别是 MSG 和 WNDCLASSEX结构,在参考手册中,可以看到WNDCLASSEX定义了一个窗口的所有参数,如使用的菜单、光标、颜色、窗口过程等,接下来的一大堆 mov 指令实际上就是在填写这个数据结构,填写完成后,最重要的两句是 mov @stWcMain.lpfnWndProc,offset WndMainProc 定义了处理消息的窗口过程, mov @stWcMain.lpszClassName,offset szClassName 定义了你要创建的类的名称,然后就是使用 RegisterClassEx 注册这个窗口类,注意,这时候窗口并没有创建,你只不过是定义好了一个子类,接下去你要用你定义的类去创建一个窗口。也就是使用 CreateWindowEx 函数去创建它。在手册中,CreateWindowEx 是这样定义的:
HWND CreateWindowEx(
DWORD dwExStyle, // extended window style
LPCTSTR lpClassName, // pointer to registered class name
LPCTSTR lpWindowName, // pointer to window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // handle to menu, or child-window identifier
HINSTANCE hInstance, // handle to application instance
LPVOID lpParam // pointer to window-creation data );
其中的参数 dwExStyle 是窗口的风格,lpClassName 就是我们自己定义的类的名字。如果大家要创建一个已经定义好的类,如 RichEdit 类等等,只要把 lpClassName 指向 RichEdit32 字符串就行了,当然这时就不用 RegisterClass 以及编写自己的窗口过程了。执行 CreateWindowEx 后,得到一个返回值就是窗口句柄,这个值在以后是要经常用到了,所以要先保存下来。这时窗口并没有在屏幕上显示出来,而是处于隐藏状态,我们要用 ShowWindow 来显示出窗口并用UpdateWindow 来绘窗口的内容。
窗口显示出来后,程序就进入一个循环----消息循环,前面我已经说过,作用是不停地接收 Windows 消息并发送给窗口过程去处理。GetMessage 从消息队列中取出一条消息,如果取得的消息不是 WM_QUIT,那么 GetMessage 返回一个非零值,否则返回零,这时候循环结束,程序执行 ExitProcess退回操作系统。TranslateMessage 将消息进行一些键盘转换,用于处理一些快捷键,DispatchMessage 将处理后的消息发回 Windows,由Windows调用窗口进程进行处理,当窗口进程处理完返回后,程序才从 DispatchMessage 返回,从而开始下一个 GetMessage 调用。这些函的参数可以参考手册。
窗口过程的分析
窗口过程有四个参数,hWnd 是本窗口的句柄,和创建窗口时返回的值相同,uMsg 是本次调用的消息类型,wParam 和lParam是消息的参数,其含义和数值根据消息的不同而不同。在本程序中,我们处理 WM_CREATE,WM_COMMAND 和 WM_QUIT 消息,然后返回0,对不处理的消息,使用 invoke DefWindowProc,hWnd,uMsg,wParam,lParam 来处理并直接用 ret 将返回值传回 Windows。在响应 WM_CLOSE 消息时,我们用 DestroyWindow 清除窗口并用PostQuitMessage 产生一条 WM_QUIT 消息,从而使程序在 消息循环调用GetMessage 时返回0,以结束消息循环并结束程序。 如何隐藏/显示任务栏
shell db Shell_TrayWnd,0 ; 任务栏的类名
invoke FindWindow,addr shell,NULL ; 先获得句柄,之后隐藏.
.if eax != 0
invoke ShowWindow,eax,SW_HIDE ; 用SW_SHOW显示
.endif
- 如何禁止/允许/显示/隐藏开始按钮?
.data?
buffer db 127 dup(?)
.data
shell db Shell_TrayWnd,0
sbar db BUTTON,0
child dd ?
slen dd ?
.code
invoke FindWindow,addr shell,NULL ; 获得状态栏句柄
mov tray, eax
invoke GetWindow,tray, GW_CHILD ; 获得状态栏的子窗口(如果有的话)
mov child, eax
.if child != 0
invoke GetClassName,child,offset buffer, sizeof buffer ;获得子窗口类名
.if eax > 0
invoke lstrlen, offset buffer ;获得类名长度
mov slen,eax
invoke CharUpperBuff,offset buffer,slen ;转为大写
invoke lstrcmp,addr buffer, addr sbar ;将类名与'BUTTON'比较
.if eax == 0
invoke ShowWindow,child,SW_HIDE ; 隐藏开始按钮
; invoke ShowWindow,child,SW_SHOW ; 显示开始按钮
; invoke EnableWindow,child,FALSE ; 禁止开始按钮
; invoke EnableWindow,child,TRUE ; 允许开始按钮
.endif
.endif
.endif
--------------------------------------------------------------------------------
- 如何创建一个真正的总在最上面窗口?
invoke SetWindowPos,hWin, HWND_TOPMOST,NULL,NULL,NULL,NULL,SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE
- 如何创建热键?比如CTRL + ALT + A
.data
hmsg db HotKey CTRL + ALT + A Works good!,0
hcap db Hotkey Example,0
.code
.if uMsg == WM_CREATE
invoke RegisterHotKey,hWnd,065h,MOD_CONTROL or MOD_ALT, 041h ; CTRL + ALT + A (041h is 65 - 065h is 101)
.elseif uMsg == WM_HOTKEY
invoke MessageBox,hWin,addr hmsg,addr hcap, MB_OK or MB_ICONINFORMATION
.elseif uMsg == WM_DESTROY
invoke UnregisterHotKey,hWin,065h
invoke PostQuitMessage,NULL
return 0
.endif
-如何获得Windows目录和系统目录?
.data
buffer db 50 dup(?)
hCap db WindowsDirectory,0
.code
invoke GetWindowsDirectory, addr buffer, sizeof buffer ; 置Windows目录于缓冲区中
; invoke GetSystemDirectory, addr buffer, sizeof buffer ;置系统目录于缓冲区中
invoke MessageBox,hWnd, addr buffer, addr hCap, MB_OK or MB_ICONINFORMATION
- 如何从我的程序打开开始菜单?
invoke SendMessage,hWnd,WM_SYSCOMMAND,SC_TASKLIST,NULL
- 如何关闭正被激活的程序 ?
.data
fwin dd ?
.code
invoke GetForegroundWindow
mov fwin,eax
invoke SendMessage, fwin, WM_CLOSE,NULL
- 如何去掉窗口标题 ?
invoke GetWindowLong,hWnd,GWL_STYLE ; 获得当前窗口类
and eax,not WS_CAPTION ; 去掉WS_CAPTION
invoke SetWindowLong,hWnd,GWL_STYLE,eax ; 设置窗口类
- 如何知道窗口是否在任务栏中(或可见)?
invoke IsWindowVisible,hWin
.if eax == TRUE
; 窗口可见
.else
; 窗口不可见
.endif
- 如何隐藏一个窗口?
.data
mirc db mIRC32,0
mhand dd ?
.code
invoke FindWindow,addr mirc, NULL ; 寻找mIRC32
mov mhand,eax
.if mhand != 0 ; 找到?
invoke ShowWindow,mhand,SW_SHOW ; 显示窗口
; invoke ShowWindow,mhand,SW_HIDE ; 隐藏窗口
.else
; mIRC32未运行...
.endif
- 如何将窗口置于前台?
invoke SetForegroundWindow, mhand
- 如何屏蔽CTRL+ALT+DEL,ALT+TAB+CTRL+ESC这些键?
invoke SystemParametersInfo,SPI_SCREENSAVERRUNNING,1,NULL,NULL
; Windows98 only 1 关闭 0 允许
- 如何确定Windows任务栏的自动隐藏特性是否被激活?
.data
AppBar APPBARDATA {} ; {} 指使用默认值... Thanks to TTom
.code
mov AppBar.cbSize, sizeof AppBar
invoke SHAppBarMessage, ABM_GETSTATE, addr AppBar ; ShellApi命令
and eax, ABS_AUTOHIDE
.if eax == TRUE
; 任务栏被隐藏
.else
; 任务栏未被隐藏
.endif
- 如何使用默认的浏览器或邮件程序?
.data
lpPage db http://win32asm,0
lpMail db .tr,0
lpOperation db open,0
.code
invoke ShellExecute,hWin,addr lpOperation, addr lpPage, NULL, NULL, SW_SHOWNORMAL
invoke ShellExecute,hWin,addr lpOperation, addr lpMail, NULL, NULL, SW_SHOWNORMAL
- 如何用Win32 API显示网络连接对话框?
include \MASM32\INCLUDE\mpr.inc
includelib \MASM32\LIB\mpr.lib
invoke WNetConnectionDialog,hWnd,RESOURCETYPE_DISK 1、80端口问题
很大一部分都来自端口问题,但是一般没装IIS的。则不会出现这个问题
2、配置文件httpd.conf问题
配置文件中的则是拼写问题了,建议每次更改前都对httpd.conf 文件备份。主要检查 LoadModule php5_module 的路径。包括有无中文字符,空格。以及ErrorLog 路径,php.ini文件路径无效等
3、第三就网上流传最广的解答办法了,直接copy了
这一般是netbios解析失败造成的。解决的办法很简单,步骤如下:
一、 在网上邻居上 点右键,菜单上选属性(R)。出来网络连接窗口,在本地连接上点右键,菜单中点属性(R)。出来本地连接 属性面板,在此链接使用下列项目中找到:Internet 协议 (TCP/IP),并点击它。在弹出的Internet 协议 (TCP/IP) 属性面板上,点击高级(V)...按钮。高级 TCP/IP 设置面板上点WINS选项标签,去掉启用 LMHOSTS 查询(L)前面的勾,点确定按钮。
二、 打开控制面板,点击Windows 防火墙,点击高级选项标签,选择本地连接,并点击旁边的设置(T)...按钮。在服务选项中找到安全 Web 服务器(HTTPS),并把它勾选上,点确定按钮。
4、第四相关软件影响。迅雷开启时,apache是启动不了的。可以关掉迅雷再试试
5、可能是php版本不是php5.0以上版。LoadModule phpX_module 读取这个模块是权限不够。一般去掉这一行apache 就可以启动了,但是php 却没加载上来。建议使用5.0以上版。
6、打开httpd.conf文件。搜索 ServerAdmin 把这行改为#ServerAdmin 保存,重启。
可能还存在各种各样的问题。
我的解决方式就是第6个。搞的我郁闷半天。不过还好启动了
启动服务错误时,如服务日志没有记录。可以使用事件查看器,查看系统的日志错误。cmd 命令:eventvwr.msc 进入。

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式