当前位置:编程学习 > C/C++ >>

孙鑫C++教程(全20讲)PPT讲义

#include <windows.h>
#include <stdio.h>

LRESULT CALLBACK WinSunProc(
HWND hwnd,
// handle to window
UINT uMsg,
// message identifier
WPARAM wParam, // first message parameter
LPARAM lParam
// second message parameter
);

int WINAPI WinMain(
HINSTANCE hInstance,
// handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine,

// command line
int nCmdShow


// show state
)
{
WNDCLASS wndcls;
wndcls.cbClsExtra=0;
wndcls.cbWndExtra=0;
wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);
wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);
wndcls.hInstance=hInstance;
wndcls.lpfnWndProc=WinSunProc;
wndcls.lpszClassName="Weixin2003";
wndcls.lpszMenuName=NULL;
wndcls.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wndcls);

HWND hwnd;
hwnd=CreateWindow("Weixin2003","北京维新科学技术培训中心",WS_OVERLAPPEDWINDOW,
0,0,600,400,NULL,NULL,hInstance,NULL);

ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);

MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}

LRESULT CALLBACK WinSunProc(
HWND hwnd,
// handle to window
UINT uMsg,
// message identifier
WPARAM wParam, // first message parameter
LPARAM lParam
// second message parameter
)
{
switch(uMsg)
{
case WM_CHAR:
char szChar[20];
sprintf(szChar,"char is %d",wParam);
MessageBox(hwnd,szChar,"weixin",0);
break;
case WM_LBUTTONDOWN:
MessageBox(hwnd,"mouse clicked","weixin",0);
HDC hdc;
hdc=GetDC(hwnd);
TextOut(hdc,0,50,"计算机编程语言培训",strlen("计算机编程语言培训"));
ReleaseDC(hwnd,hdc);
break;
case WM_PAINT:
HDC hDC;
PAINTSTRUCT ps;
hDC=BeginPaint(hwnd,&ps);
TextOut(hDC,0,0,"维新培训",strlen("维新培训"));
EndPaint(hwnd,&ps);
break;
case WM_CLOSE:
if(IDYES==MessageBox(hwnd,"是否真的结束?","weixin",MB_YESNO))
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
return 0;
}





--------------------Configuration: WinMain - Win32 Debug--------------------
Linking...
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/WinMain.exe : fatal error LNK1120: 1 unresolved externals
执行 link.exe 时出错.

WinMain.exe - 1 error(s), 0 warning(s)

求解决方法
答案:/subsystem:console是控制台程序;
/subsystem:windows是Windows程序;

/subsystem:console改为/subsystem:windows后,引导程序会调用WinMain,否则会调用main。

操作系统装载应用程序后,做完初始化工作就转到程序的入口点执行。程序的默认入口点实际上是由连接程序设置的,不同的连接器选择的入口函数也不尽相同。在 VC++下,连接器对控制台程序设置的入口函数是 mainCRTStartup,mainCRTStartup 再调用你自己编写的 main 函数;对图形用户界面(GUI)程序设置的入口函数是 WinMainCRTStartup,WinMainCRTStartup 调用你自己写的 WinMain 函数。而具体设置哪个入口点是由连接器的“/subsystem:”选项参数确定的,它告诉操作系统如何运行编译生成的.EXE文件。

Microsoft Visual Studio集成开发环境会设置各种链接器开关,是链接器将子系统的正确类型嵌入最终生成的可执行文件中。对于CUI(Console User Inte易做图ce,控制台用户界面)程序,这个链接器开关是/SUBSYSTEM:CONSOLE,对于GUI(Graphical User Inte易做图ce,图形用户界面)程序,则是/SUBSYSTEM:WINDOWS。
Windows应用程序必须有一个入口点函数,应用程序开始运行时,这个函数会被调用。C/C++开发人员可以使用一下两种入口点函数:

int WINAPI _tWinMain(

HINSTANCE hInstanceExe,


HINSTANCE,


PTSTR pszCmdLine,


int nCmdShow);

int _tmain(


int argc,


TCHAR *argv[],


TCHAR *envp[]);
具体的符号拒绝与我们是否要使用Unicode字符串。操作系统实际并不调用我们所写的入口点函数。相反,它会调用由C/C++运行库实现并在链接时使用-entry:命令行选项来设置一个C/C++运行时启动函数。该函数初始化C/C++运行库,确保在我们的代码开始执行之前,声明的任何全局和静态C++对象都被正确地构造。


链接器根据/SUBSYSTEM链接器开关,选择相应的C/C++运行库启动函数。如果指定/SUBSYSTEM:CONSOLE,链接器会寻找main或wmain,并选择相应C/C++运行时启动函数。如果没有找到这两个函数,链接器将返回“unresolved external symbol”(无法解析的外部符号)错误。/SUBSYSTEM:WINDOWS的情况类似。
如果我们移除/SUBSYSTEM链接器开关,链接器将自动判断应该将应用程序设备哪一个子系统,链接器会检查代码中包括4个函数中的哪一个(WinMain,wWinMain,main,wmain),并据此推算可执行文件应该是哪个子系统,以及应该在可执行文件中嵌入哪个C/C++启动函数。
所以我们在创建一个新项目时如果错误的选择了项目的类型,我们可以更改/SUBSYSTEM:开关,或则直接删除/SUBSYSTEM:开关,让链接器自动判断应该将应用程序设为哪个子系统。

上一个:谁能给一张c++函数表格
下一个:c++程序设计的特点在哪呀???

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,