Windows编程
本文整理自百科、知乎与 科学家的世界
问题一:为什么开发windows应用程序不用c 而用.net,java,c++?
用 c+windows API 开发windows 应用程序 比用.net,java,c++开发有什么缺点或优点?
- C/C++,现在的软件公司对这种人才需求更多。用这种语言写出来的程序是真正的exe可执行文件。是有系统启动运行的。 而Java和.NET就不一样了。
- Java是基于解释的,你写出的程序不是由系统运行的。是由jdk的一个叫java.exe或者javaw.exe的程序运行。速度肯定要比前者慢。
- 而.NET即使看起来是exe文件,但是也是有.NETframework运行的。
对于初学者Java和C#会简单些。
C/C++是调用mfc就是windows的系统基础类执行的。
Java是用jdk运行的。
C#是用.NETframework运行的。
问题二(知乎):如何学习
Windows 编程
1、请看《windows程序设计》(很经典的一本书,分上下两册,可以买,可以下载电子版)更接近
C 语言方式的使用 windows api 的编程方式,好处是,代码直观,最适合理解 windows gui 的运作,程序员和系统之间的分工协作职责划分。缺点是,开发效率低,不易学习。但是学好了,感觉是非常爽,非常自由的。不过在今天使用这种方式写 windows 程序的人,我几乎见不到。开发成本巨高昂无比。更多请看:Windows
程序设计 复习笔记(共 81 问)
《windows 核心编程》:这是一个名家写的书。算是《windows 程序设计》的进阶篇。里面提到的是一些更专业的技术。是你在掌握了windows
程序设计后应该读的书。这个人后来好像有写了《C# via CLR》。
2、Windows编程现在仍然是一坑。
如果你想Win下面用c++编程,那只能写原生程序,首先遇到的问题是GUI界面,这个问题非常复杂。因为20多年来,Windows原生GUI程序编程的复杂度没有降低过,可以说相当困难。(原因自然是光头鲍尔默在技术上的无知,把精力都放在.net上去了,但是.net几乎没人待见)
你有几个选择:
- 直接调用windows api绘制界面。非常繁琐,我建议你不要把生命浪费在这个上面。
- MFC,20年以上的历史,一个微软VC6.0时代老掉牙的C++ gui界面库,过时而且不好用。
- QT是一个第三方库。是一个不错的选择,但是它这个框架有点庞大,运行效率不是很高,总得来说是业余编程最佳选择了。
- WTL微软程序员业余写的库,仍然非常简陋的库,大量东西等着你去实现。
所以你看,Windows原生程序编写最大的问题是找不到合适的界面库,你想编写带界面的原生WIN程序非常吃力,我们看到这么多年来Windows上的程序翻来覆去就是QQ等那些老面孔,这根Win平台原生GUI编程太困难有很大关系。对比之下Mac、ios/安卓编写GUI程序都简单的多。
除非,你用.net框架。.net框架不能编写原生程序,用c#编写,跟c++关系不大了。
所以如果你是一个学生,我不建议你学这个,你可以学习下苹果/安卓手机平台编程、或者web编程、或者c++/COCOS2Dx游戏编程,都比学windows gui编程有意义的多,win平台已经到顶了,已经不是未来最大的趋势了。(这观点此楼主太)
3、学Windows编程,最好是将C#和C++结合起来。
现在的Windows上,主流的开发方法是:界面和大部分不影响效率的功能是用C#实现的。非常影响效率的部分功能用c++的实现,并作为程序的动态链接库调用。
最好不要用C++来编写界面和普通的功能,事倍功半!
什么是Windows编程
所谓Windows编程就是在Windows平台上开发,并且运行于Windows平台上的程序,当然,开发的时候运用的东西是Windows API或者封装之后的Windows
API。
为什么要学Windows编程
有人说,我学的是Java,我不需要跟系统打交道。是的,你说的是对的,但是,这并不意味着学习Windows编程是不必要的,事实上,Java的底层使用的也是Windows API,比如,Java的Socket模块使用的肯定是Windows的WS2_32.dll导出的API。所谓的高层语言,其实在具体跨平台的时候用的是相应的本地系统提供的API,比如创建进程,在Java里面肯定有相应的API,这些API底层的实现在Windows上调用的是CreateProcessA(W),在Linux上调用的是fork之类的函数。学习Windows编程能让你更了解操作系统,也让你更了解程序的运行原理。当然,你可以学习Linux平台的编程,不过,两者之间其实差不多,在Windows中有的API在Linux中其实是有与之对应的,我对于Windows平台和Linux平台的编程都学过,只是用得最多的是Windows。
我需要什么基础才能学习Windows编程
事实上,我可以告诉你,你需要的基础就是C语言,除了这个之外,你不需要什么其它的基础,你并不需要什么C++的基础,汇编基础之类的东西,当然,你最好是能理解一些操作系统的相关东西。
我需要什么工具
关于工具,事实上你只需要一个Windows操作系统和一个VisualStudio 2012就可以(如果你使用的是Visual Studio 2008(2010)也可以)。作为一个初学者,什么版本的Windows操作系统无所谓,只要是WindowsXP及以后的版本都可以,虽然有些API只有在NT
6.0之后才有,不过,那对于初学者是不需要的。
Windows程序员需要学什么
经常发现有人在网上提出这样的问题,现实中也确实有不少人在经历了3-5年的Windows开发之后就开始迷失方向,每天浑浑噩噩混日子,可能是因为这个问题粒度太大,没人愿意花时间回答,希望本文可以抛砖引玉,给大家节省些时间,同时也希望园子里面的兄弟们能尽力的补充,从而使这篇文章可以帮助更多的后来人。
首先说明的是,本文提到的各种技术不分先后,没有顺序,虽然先学什么,再学什么对某些人来说可能更方便,但是这些都不是绝对的,因为每个人的情况不同。
Windows开发首先必须学习的就是操作系统的API,因为其他的一切都是构建于OS之上,所谓九层之台,起于垒土,如果你对linux的系统调用很熟悉就会发现其实他们大同小异,都是应用程序在使用系统提供的功能。
接下来是MFC,有了MFC你才真正的可以干点开发,因为MFC实在是太全了,几乎封装了所有的Windows
API, 消息循环,COM实现…
到了此地,你可以开始学习调试技术了,熟悉了调试的各种技巧才可以做到事半功倍,得心应手。
接下来是组建对象模型COM,作为windows的基石,不懂COM,很难说自己精通windows编程,因为即使现在的.NET
framework也是构建于COM之上,很多问题还是需要SOS到底层去调试。
当你懂得了COM的精髓,你应该开始学习ATL了,这个类库可以使你的COM开发更加得心应手。
说到ATL就不能不提到他的前辈STL,这个出自于标准C++的类库在windows上同样也得到了很好的支持,有了STL在你有一天想转linux开发也同样会用得上。
Windows 8中的WinRT现在还没有应用于实际开发,现有的技术中.NET 是非常值得学习的,因为.NET 的主旨是提高程序员的开发效率,在这个浮躁的世界,开发效率有时候能够代表一切。
从COM到.NET只有一步之遥,.NET 其实是从COM+演化而来,具体细节请参看 Don
Box的《.NET 本质论》了解了这些会使你对.NET的认识上升到一个新的层面。
接下来是C# 因为这家伙是.NET的嫡系部队,除了IL,这家伙可以说和.NET 的关系最为亲近,大部分的新功能都会最先在其中加以体现。当你熟悉了C#, BCL,《CLR
via C#》可以说这个时候你已经可以胜任基本的C#开发了,可以很快写出一个小工具,完成一个相关的task。
接下来是WCF和WPF,做分布式开发少不了WCF,同样华丽的界面少不了XAML,WPF。
大概罗列了一些,其实每个主题仔细探究下去都很有韵味,还有需要说的是,其实Windows上面好多的东西都和UNIX很像,比如PowerShell明显是为了像UNIX一样,给开发者提供一个更强大的shell, 如果有兴趣,触类旁通一下,也很是有趣。
还有:
LINQ改变了我们的数据操作方式,统一了数据操作模型,经常操作数据的兄弟,你值得拥有。
F#作为一种函数式编程语言也很值得研究,由于本人使用不多,在此不作评价。
另外:
作为基础的算法;
作为提升功力的设计模式,UML;
作为改善系统性能的重构;
作为大部分分布式核心的TCP/IP;
等等主题也是值得大家研究的。
最后借鲁迅的话收尾:其实地上本没有路,走的人多了也便成了路,希望大家不要把时间都浪费了,原来还有好多东西可以去钻研。
不当之处望大家批评、指正、拍砖, 并提出您的宝贵的意见和补充。
转自:solidmango
练习
第一个工程
1)打开Visual Studio,如下地建一个工程
2)选择一个空的工程
3) 新建一个文件 添加一个cpp文件的。
4)输入如下代码
#include <windows.h>
#pragma comment(linker, "/entry:\"main\" /subsystem:\"windows\"")
int main()
{
MessageBox(NULL, TEXT("Hello,World"),TEXT("NULL"), MB_OK);
}
5)按下 Ctrl + F5
此时可以运行程序了,是不是看到了一个小窗口呢?是不是这此代码比较熟悉呢?
是的,事情就是这样,你看到的就是Windows上开发所需要的一切。
代码解释:
第一行:第一行是#include <windows.h>,任何Windows平台上的应用程序肯定需要引用一些Windows的函数或者变量,而这些函数或者变量的声明就在Windows.h里面,所以我们需要包含它,这跟大家包含stdio.h一样的道理。
第二行:也许大家看到的Windows程序是以WinMain开头的,然而,你们在这里面看到的是main?有人怀疑我写错了,事实上,我没有写错,所谓的main函数是一个逻辑上的概念,也就是告诉链接器,我这个程序要从哪里开始执行,C(++)里面的入口函数是main,Windows上是WinMain,这些并没有错,当然,也允许我们自己设定入口函数。这里面的#pragma comment(linker, "/entry:\"main\" /subsystem:\"windows\"")里面的/entry其实是设置入口函数,/subsystem其实是设置子系统(gui的或者console的),gui的程序是没有黑框框的,console的程序是大家平时看到的一个黑框框,大家的第一次hello,world基本上是交给它的,正如大家的第一次上网基本交给了IE一样。
第三行:第三行是一个函数调用,大家肯定知道的对吧,这个函数调用的是MessageBox,即一个Windows里面的API,定义于user32.dll里面。为了方便大家写程序,我建议大家安装一个叫做msdn的东西,
细节说明:
- TEXT是什么
把鼠标放在TEXT上面,然后按下F12,你会看到如下的说明,其定义等价于如下的:
#ifdef UNICODE #define TEXT(queto) L##queto #else #define TEXT(queto) queto #endif
从中可以从字面地看出来吧
- UNICODE是什么
在C语言中我们可以一般写字符串中都是用“Hello,World”这种写法,而没有上面的那种TEXT("Hello,World")的写法,在Windows里面,为了便于操作系统的移植,使用了两种字符表示,一个是多字节码,一种是UNICODE表示,如果在一个ascii字符串前面加上L,那么它就变成了UNICODE串,比如L"ABC"
可以刚才如下网址:http://baike.baidu.com/view/40801.htm
- ##是什么
在Windows平台的C语言中有##表示串连接,比如“ABC”##"DEF"你就得到了"ABCDEF"了,这个估计很多人都不知道。这个东西在MFC的实现中用得特别多。
- MessageBox是一个函数?
其实 ,MessageBox不是一个函数,与之相关的函数有两个,MessageBoxA与MessageBoxW,根据是否使用UNICODE串从而定义MessageBox是MessageBoxA还是MessageBoxW,并且,在user32.dll里面同时实现了这两个API,当然MessageBoxA的实现中会调用MessageBoxW。
通过 dumpbin -exports user32.dll可以看到如下的结果
dumpbin -exports可以看出一个dll里面导出了什么函数,这个工具是由visual studio sdk提供的,大家安装完visual sutdio之后就会自动安装这个工具,不需要单独下载。
Windows开发的常识
1)窗口
Windows中最基本的概念也许就是窗口了,每一个前台程序都至少有一个窗口,一个窗口也是你可以看到的部分,比如,QQ的登录窗口
2)句柄
Syntax
DWORD WINAPI SuspendThread(
__in HANDLE hThread
);
又比如,你想读一个文件,其函数ReadFile的原型如下:(第一个参数就是一个文件的句柄。)
BOOL WINAPI ReadFile(
__in HANDLE hFile,
__out LPVOID lpBuffer,
__in DWORD nNumberOfBytesToRead,
__out_opt LPDWORD lpNumberOfBytesRead,
__inout_opt LPOVERLAPPED lpOverlapped
);
3)进程
4)线程
基本的正常的Windows程序
代码
#include <windows.h>
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("BossJue");
HWND hwnd;
MSG msg;
WNDCLASSEX wndclassex = {};
wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WndProc;
wndclassex.cbClsExtra = ;
wndclassex.cbWndExtra = ;
wndclassex.hInstance = hInstance;
wndclassex.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndclassex.hCursor = LoadCursor (NULL, IDC_ARROW);
wndclassex.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
wndclassex.lpszMenuName = NULL;
wndclassex.lpszClassName = szAppName;
wndclassex.hIconSm = wndclassex.hIcon; if (!RegisterClassEx (&wndclassex))
{
MessageBox (NULL, TEXT ("RegisterClassEx failed!"), szAppName, MB_ICONERROR);
return ;
}
hwnd = CreateWindowEx (WS_EX_OVERLAPPEDWINDOW,
szAppName,
TEXT ("WindowTitle"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL); ShowWindow (hwnd, iCmdShow);
UpdateWindow (hwnd); while (GetMessage (&msg, NULL, , ))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static const LPTSTR text = TEXT("Hello,World");
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
return (); case WM_PAINT:
hdc = BeginPaint (hwnd, &ps);
TextOut (hdc, , , text, lstrlen(text));
EndPaint (hwnd, &ps);
return (); case WM_DESTROY:
PostQuitMessage ();
return ();
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
运行,按下Ctrl + F5,你可能会碰到如下的链接错误:
不要急,这个错误的设置是因为Windows把这个程序当作console程序,而console程序默认入口函数是main,而我们在这里面并没有定义main,而是定义了一个叫WinMain的入口函数,所以链接器不认,而我们希望的却是编译器认为我们这个程序是一个GUI程序,GUI程序的入口函数是WinMain(如果你用#pragma comment(linker…………)修改的话当然也是可以的,这种方法我在第一章里面就写到了。当然,我们还可以直接在Visual Studio IDE里面直接设置,方法是打开项目属性,然后如下设置:
这样设置之后,再按Ctrl + F5,有没有看到如下的一个窗口呢?
对,就是这样,你看到的就是一个正常的Windows程序的编写。
代码解释
编写Windows程序的过程
CreateWindowEx (WS_EX_OVERLAPPEDWINDOW, szAppName, TEXT ("WindowTitle"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
剩下的
更多资料参考: Windows编程基础、Windows API简明教程
Windows编程的更多相关文章
- 【Windows编程】系列第六篇:创建Toolbar与Statusbar
上一篇我们学习了解了如何使用Windows GDI画图,该应用程序都是光光的静态窗口,我们使用Windows应用程序,但凡稍微复杂一点的程序都会有工具栏和状态栏,工具栏主要用于一些快捷功能按钮.比如典 ...
- 【Windows编程】系列第十一篇:多文档界面框架
前面我们所举的例子中都是单文档界面框架,也就是说这个窗口里面的客户区就是一个文档界面,可以编写程序在里面输入或者绘制文本和图形输出,但是不能有出现多个文档的情况.比如下面的UltraEdit就是一个典 ...
- 【Windows编程】系列第十篇:文本插入符
大家知道,在使用微软的编程环境创建工程时会让你选择是控制台模式还是Windows应用程序.如果选择控制台的console模式,就会在运行时出现一个黑洞洞的字符模式窗口,里面就有等待输入一闪一闪的插入符 ...
- 【Windows编程】系列第八篇:通用对话框
上一篇我们学习了菜单的基本编程,本篇来了解一下通用对话框的使用.Windows系统之所以是目前最流行的桌面系统,也是因为Windows有一套标准化,统一友好的交互界面,比如菜单.工具栏.状态栏以及各个 ...
- 【Windows编程】系列第七篇:Menubar的创建和使用
上一篇我们学习了利用windows API创建工具栏和菜单栏,与上一篇紧密联系的就是菜单栏,菜单栏是一个大多数复杂一些的Windows应用程序不可或缺的部分.比如下图就是Windows自带的记事本的菜 ...
- 【Windows编程】系列第五篇:GDI图形绘制
上两篇我们学习了文本字符输出以及Unicode编写程序,知道如何用常见Win32输出文本字符串,这一篇我们来学习Windows编程中另一个非常重要的部分GDI图形绘图.Windows的GDI函数包含数 ...
- 【Windows编程】系列第九篇:剪贴板使用
上一篇我们学习了常见的通用对话框,本篇来了解剪贴板的使用,它常用于复制粘贴功能. 剪贴板是Windows最早就加入的功能,由于该功能非常实用,我们几乎每天都会使用到.通过剪贴板,我们就可以将数据从一个 ...
- 【Windows编程】系列第四篇:使用Unicode编程
上一篇我们学习了Windows编程的文本及字体输出,在以上几篇的实例中也出现了一些带有“TEXT”的Windows宏定义,有朋友留言想了解一些ANSI和Unicode编程方面的内容,本章就来了解和学习 ...
- 【Windows编程】系列第三篇:文本字符输出
上一篇我们展示了如何使用Windows SDK创建基本控件,本篇来讨论如何输出文本字符. 在使用Win32编程时,我们常常要输出文本到窗口上,Windows所有的文本字符或者图形输出都是通过图形设备接 ...
- Windows编程入门程序详解
引用:http://blog.csdn.net/jarvischu/article/details/8115390 1. 程序 /******************************* ...
随机推荐
- 正则表达式:Python3中的应用简介
正则表达式:Python3中的应用简介 一.正则表达式 1,概述 正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学 ...
- ping主机脚本
#!/bin/bash #ping net='172.16.1' uphosts=0 downhosts=0 for i in {1..254};do ping -c 1 -w 1 ${net}.${ ...
- mac下Appium环境配置
一.Appium环境搭建 1.xcode(需要OS X版本支持): 下载对应版本的xcode(支持对应手机系统),解压,拖入应用程序. xcode下载地址:https://developer.appl ...
- curator的版本兼容问题(需注意)
Curator 存在版本兼容问题. Curator 2.x.x-兼容两个zk 3.4.x 和zk 3.5.x, Curator 3.x.x-兼容兼容zk 3.5. Versions The are c ...
- spring集成spring mvc 和hibernate详解
1.配置IOC容器 <!-- 配置IOC容器 --> <context-param> <param-name>contextConfigLocation</p ...
- eclipse向上/下复制一行(或者多行)的快捷键失效的基本解决方法
在eclipse中,快捷键Ctrl+Alt+↓是向下复制选中的行,快捷键Ctrl+Alt+↑是向上复制选中的行. 这两个快捷键也是我常用的快捷键之一,以前也遇到失效. 所以现在记录一个解决的方法: 在 ...
- ThinkPad.E440_FN键反了
1.一直不知道,为何我的 FN键反了(Fn+F1 才是F1的功能),想改过来.查到是 BIOS中改,但是 BIOS里面没有 那些个修改的选项,于是 还原了BIOS的设置,于是出问题了... 2.问题1 ...
- TCP_AIO_Server_ZC_01
ZC: 这个例子是,1个skt 投递 1个未决的接收操作 1.package aio.Client; 1.1.这是一个 测试的客户端的代码: package aio.Client; import ja ...
- LeetCode第[5]题(Java):Longest Palindromic Substring 标签:String、动态规划
题目中文:求最长回文子串 题目难度:Medium 题目内容: Given a string s, find the longest palindromic substring in s. You ma ...
- python之linecache使用
Python linecache模块缓存读取大文件指定行 linecache模块的作用是将文件内容读取到内存中,进行缓存,而不是每次都要从硬盘中读取,这样效率提高很多,又省去了对硬盘IO控制器的频繁操 ...