|
C++操作符的优先级 | 操作符及其结合性 | 功能 | 用法 | L L L | :: :: :: | 全局作用域 类作用域 名字空间作用域 | ::name class::name namespace::name | L L L L L | . -> [] () () | 成员选择 成员选择 下标 函数调用 类型构造 | object.member pointer->member variable[expr] name(expr_list) type(expr_list) | R R R R R | ++ -- typeid typeid 显示强制类型转换 | 后自增操作 后自减操作 类型ID 运行时类型ID 类型转换 | lvalue++ lvalue-- typeid(type) typeid(expr) cast_name<type>(expr) | R R R R R R R R R R R R R R | sizeof sizeof ++ -- ~ ! - + * & () new delete delete[] | 对象的大小 类型的大小 前自增操作 前自减操作 位求反 逻辑非 一元负号 一元正号 解引用 取地址 类型转换 创建对象 释放对象 释放数组 | sizeof expr sizeof(type) ++lvalue --lvalue ~expr !expr -expr +expr *expr &expr (type)expr new type delete expr delete []expr | L L | ->* .* | 指向成员操作的指针 指向成员操作的指针 | ptr->*ptr_to_member obj.*ptr_to_member | L L L | * / % | 乘法 除法 求模(求余) | expr * expr expr / expr expr % expr | L L | + - | 加法 减法 | expr + expr expr - expr | L L | << >> | 位左移 位右移 | expr << expr expr >> expr | L L L L | < <= > >= | 小于 小于或等于 大于 大于或等于 | expr < expr expr <= expr expr > expr expr >= expr | L R | == != | 相等 不等 | Expr == expr Expr != expr | R | & | 位与 | Expr & expr | R | ^ | 位异或 | Expr ^ expr | R | | | 位或 | Expr | expr | R | && | 逻辑与 | Expr && expr | R | || | 逻辑或 | Expr || expr | R | ?: | 条件操作 | Expr ? expr : expr | R R R R R | = *=,/=,%= +=,-= <<=,>>= &=,|=,^= | 赋值操作 符合赋值操作 | Lvalue= expr Lvalue+= expr …… | R | throw | 抛出异常 | Throw expr | L | , | 逗号 | Expr, expr | 记忆方法: --摘自《C语言程序设计实用问答》 -吕凤翥 吕 涛著 问题:如何记住运算符的15种优先级和结合性? 解答:C语言中运算符种类比较繁多,优先级有15种,结合性有两种。 如何记忆两种结合性和15种优先级?下面讲述一种记忆方法。 结合性有两种,一种是自左至右,另一种是自右至左,大部分运算符的结合性是自左至右,只有单目运算符、三目运算符的赋值运算符的结合性自右至左。 优先级有15种。记忆方法如下: 记住一个最高的:构造类型的元素或成员以及小括号。 记住一个最低的:逗号运算符。 剩余的是一、二、三、赋值。 意思是单目、双目、三目和赋值运算符。 在诸多运算符中,又分为: 算术、关系、逻辑。 两种位操作运算符中,移位运算符在算术运算符后边,逻辑位运算符在逻辑运算符的前面。再细分如下: 算术运算符分 *,/,%高于+,-。 关系运算符中,》,》=,《,〈=高于==,!=。 逻辑运算符中,除了逻辑求反(!)是单目外,逻辑与(&&)高于逻辑或(||)。 逻辑位运算符中,除了逻辑按位求反(~)外,按位与(&)高于按位半加(^),高于按位或(|)。 这样就将15种优先级都记住了,再将记忆方法总结如下: 去掉一个最高的,去掉一个最低的,剩下的是一、二、三、赋值。双目运算符中,顺序为算术、关系和逻辑,移位和逻辑位插入其中。
如果你的工作长期与某个领域相关,比如说长期做直接体绘制(DVR)方面的开发,那么你可能经常使用自己的传递函数类,如果每一个工程你都把传递函数类的.h和.cpp文 件添加进去会比较麻烦,其实,我们可以像使用opengl的库那样来用你自己的类,做法就是把你写好的类封装成dll,具体做法如下: 第一步:制作dll 利用VC6新建工程时选择win32 dynamic-Link Library(空的工程),然后添加头文件和cpp文件。假设你要封装的类的名成是TransferFunction,添加头文件 TransferFunction.h和TransferFunction.cpp到工程中。并将TransferFunction.h修改成: class __declspec(dllexport) TransferFunction { ... } 从而说明以后从dll要被导出的类是哪一个。这样编译完就会产生TransferFunction.dll和TransferFunction.lib两个文件。 第二步:如何使用这个dll 当已经生成dll后,有两种方法可以在其它程序中调用dll中的类和成员函数: 方法一: 1)把TransferFunction.dll和TransferFunction.lib复制到调用程序的执行路径下,注意不是debug路径下。 2)在project->setting->link里添加TransferFunction.lib(或者用#pragma comment(lib, "TransferFunction.lib") ) 3)把TransferFunction.h中的__declspec(dllexport)改成__declspec(dllimport) 然后复制到调用程序的执行路径下。 4)最后在主程序中就可以通过包含TransferFunction.h来使用TransferFunction类和它的成员函数。 方法二(推荐): 在方法一中,你每次建立一个工程都需要把 TransferFunction.dll,TransferFunction.lib,TransferFunction.h三个文件拷贝到工程里面 去,事实上这只发挥了dll对类的代码保护的功能,并没有多大的减轻编程人员的工作量,下面的方法可以减少编程人员的工作量,具体步骤: 1:将TransferFunction.dll扔到windows/system32下 2:将.TransferFunctionlib扔到VC的lib目录里 3:将方法一中的TransferFunction.h扔到VC的include目录里 4:同方法一的最后一步。 以后你就可以像使用Opengl的glut、glui等库一样使用你自己封装的一个经常复用的类了。
vs2010打开某个工程 ,转换成功之后,在工程目录看见一个sdf文件和一个ipch文件夹,都超大(起码几十M),我一个四百多k 的工程,结果用vs打开过后变成了两百多兆。 这个详细点的解释 大家也许发现了,visual studio 2010 中新建一个项目会同时建立一个ipch目录与sdf文件,即使你删掉它,再次打开工程时还是会重新建立。动辄30、50M的容量让我们心里很不爽。其实这 是2010的一个新功能,与智能提示,错误提示,代码恢复、团队本地仓库等等息息相关的东西。如果大家觉得很不爽可以关掉它。Tools —— Options —— Text Editor —— C/C++ —— Advanced ——Disable Database 设置为True,默认为false。这样,你关闭visual后删掉工程目录下的ipch与sdf就不会再产生了 但是这样的办法会产生另外的一些问题,可能会导致其他的一些功能不能使用。 另外一种解决方法是: Tools->Options->Text Editor->C/C++->Advanced,在 Fallback Location 的属性组中,将"Always Use Fallback Location"设置为 true,将"Do Not Warn If Fallback Location Used" 设置为 true ,然后删除解决方案目录下的 sdf 文件和 ipch 目录,再次打开解决方案,发现这些烦人的东西已经不见了。 那么那些文件放置到那里了呢?看 "Fallback Location" 属性说明:这是存储浏览信息数据库和 IntelliSense 文件的第二个位置,如果不指定则放置到临时目录中;到临时目录一看,里面有一个 VC++ 的目录,都在那个目录里面呢。 可以在 "Fallback Location" 属性中,设置一个固定的路径来存储这些文件,比如D:\VS2010Temp,这样也比较好管理这些庞大的臃肿的文件,可以定期清理掉它们,释放出硬盘空间!
1.1使用系统提供的OnTimerSet函数Timer(m_hWnd,1,1000,NULL); //一个1秒触发一次的定时器 在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了 于是SetTimer函数的原型变为: UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD)) 当使用SetTimer函数的时候,就会生成一个计时器。函数中nIDEvent指的是计 时器的标识,也就是名字。nElapse指的是时间间隔,也就是每隔多长时间触发一次事件。第三个参数是一个回调函数,在这个函数里,放入你想要做的事情 的代码,你可以将它设定为NULL,也就是使用系统默认的回调函数,系统默认认的是onTime函数。这个函数怎么生成的呢?你需要在需要计时器的类的生 成onTime函数:在ClassWizard里,选择需要计时器的类,添加WM_TIME消息映射,就自动生成onTime函数了。然后在函数里添加代 码,让代码实现功能。每隔一段时间就会自动执行一次。 例: SetTimer(1,1000,NULL); 1:计时器的名称; 1000:时间间隔,单位是毫秒; NULL:使用onTime函数。 当不需要计时器的时候调用KillTimer(nIDEvent); 例如:KillTimer(1); 1.2 调用回调函数 此方法首先写一个如下格式的回调函数 void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime); 然后再用SetTimer(1,100,TimerProc)函数来建一个定时器,第三个参数就是回调函数地址。 二. 或许你会问,如果我要加入两个或者两个以上的 timer怎么办? 继续用SetTimer函数吧,上次的timer的ID是1,这次可以是2,3,4。。。。 SetTimer(2,1000,NULL); SetTimer(3,500,NULL); 嗯,WINDOWS会协调他们的。当然onTimer函数体也要发生变化,要在函数体内添加每一个timer的处理代码: onTimer(nIDEvent) { switch(nIDEvent) { case 1:........; break; case 2:.......; break; case 3:......; break; } }
1:图形绘制可使用easyX提供的graphics.h头文件
1.BOOL C***Dlg::OnInitDialog() { //禁止关闭对话框 CMenu* pMenu = this->GetSystemMenu(FALSE); pMenu->ModifyMenu(SC_CLOSE,MF_BYCOMMAND | MF_GRAYED ); //禁止在任务管理器中关闭进程 SetTimer(1,m_nTimer,NULL);//设置1号定时器,循环调用stopKillProcess()函数,禁止任务管理器中关闭进程 } 2.void CClientTracerDlg::stopKillProcess()//禁止任务管理器中关闭进程 { HWND hwnd; int iItem=0; LVITEM lvitem, *plvitem; char ItemBuf[512],*pItem; DWORD PID; HANDLE hProcess; // 查找任务管理器ListView窗口句柄 hwnd=::FindWindow("#32770",_T("Windows 任务管理器")); hwnd=::FindWindowEx(hwnd,0,"#32770",0); hwnd=::FindWindowEx(hwnd,0,"SysListView32",0); // Windows任务管理器尚未启动则返回 if (!hwnd) return; else { // 没有指定目标进程则返回 iItem=::SendMessage(hwnd,LVM_GETNEXTITEM,-1,LVNI_SELECTED); if (iItem==-1) return; else { // 获取进程句柄操作失败则返回 GetWindowThreadProcessId(hwnd, &PID); hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,PID); if (!hProcess) return; else { plvitem=(LVITEM*)VirtualAllocEx(hProcess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE); pItem=(char*)VirtualAllocEx(hProcess, NULL, 512, MEM_COMMIT, PAGE_READWRITE); // 无法分配内存则返回 if ((!plvitem)||(!pItem)) return; else { lvitem.cchTextMax=512; lvitem.iSubItem=0; //ProcessName lvitem.pszText=pItem; WriteProcessMemory(hProcess, plvitem, &lvitem, sizeof(LVITEM), NULL); ::SendMessage(hwnd, LVM_GETITEMTEXT, (WPARAM)iItem, (LPARAM)plvitem); ReadProcessMemory(hProcess, pItem, ItemBuf, 512, NULL); // 比较字符串,匹配进程映像名 CString str = (CString)ItemBuf; if(str.CompareNoCase(_T("ClientTracer.exe")) == 0) { HWND hWnd=::FindWindow(NULL,_T("Windows 任务管理器")); ::SendMessage(hWnd,WM_DESTROY,0,0); Sleep(100); ::MessageBox(NULL,_T("禁止关闭系统关键进程!"),_T("提示"),MB_ICONERROR | MB_OK); } } } } } //释放内存 CloseHandle(hwnd); CloseHandle(hProcess); VirtualFreeEx(hProcess, plvitem, 0, MEM_RELEASE); VirtualFreeEx(hProcess, pItem, 0, MEM_RELEASE); } 3.定时器设置调用stopKillProcess(),也可以多线程调用stopKillProcess() void C***Dlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default if(nIDEvent == 1) { stopKillProcess(); } CDialog::OnTimer(nIDEvent); }
使用CreateProcess函数时,有一组参照代码如下 PROCESS_INFORMATION pi; STARTUPINFO si={sizeof(si)}; DWORD dwExitCode; BOOL fsuccess=CreateProcess(_T("C:\\Users\\Administrator\\Desktop\\explorer\\Debug\\explorer.exe"),NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi); if (fsuccess) { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } si参数必须制定,在创建进程时需要是使用这个结构体的成员
::SendMessage( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ); 参数1:目的窗口的句柄 参数2:系定义消息类型 参数3:消息参数 参数4:消息参数 在接受该消息的窗口函数中添加消息处理函数即可
#include <iostream> #include <fstream> #include <afx.h> using namespace std;
int main() { char path_buffer[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; GetModuleFileName(NULL,path_buffer,MAX_PATH);//得到当前路径 _splitpath( path_buffer, drive, dir, fname, ext );//拆分当前路径 cout<<path_buffer<<endl; CString cStr,temp; temp.Format("%s",drive); cStr+=temp; temp.Empty(); temp.Format("%s",dir); cStr+=temp; temp.Empty(); temp.Format("%s","\\aa.jpg");//将路径拼接成想要的文件路径 cStr.Delete(cStr.GetLength()-1,1);//去掉不包含文件名的路径的最后一个\,否则编译器会误会有转义字符 cStr+=temp; temp.Empty(); cStr.Replace("\\","\\\\"); cStr.TrimRight(); //cout<<cStr<<endl; const char* filename =cStr.GetBuffer(sizeof(cStr));//将路径赋值给一个const char* 的常量 //cout<<filename<<endl; ifstream ifile(filename,iostream::binary);//使用 ofstream ofile("D:\\aa.jpg",iostream::binary); try { if (ifile==NULL) { throw -1; } ofile<<(ifile.rdbuf()); } catch (int e) { cout<<"error"<<endl; } ifile.close(); ofile.close(); system("pause"); return 0; }
CString的GetBuffer:它的作用是返回一个可写的缓冲指针。 example: CString s(_T("File.ext")); LPTSTR p = s.GetBuffer(); CString的ReleaseBuffer: 不给它传递参数,它使用默认值 0,意思是:"给我这个字符串的指针,我保证不加长它"。 当调用 ReleaseBuffer 时,字符串的实际长度会被重新计算,然后存入 CString 对象中。
|