存档

文章标签 ‘vc’

成功完成一个小程序-屏蔽开始菜单(win)键

2008年1月11日 没有评论

    玩魔兽时经常把alt按成了win,于是用vc写了个小程序,成功屏蔽win键。

    源代码很简单,用了个底层钩子,

SetWindowsHookEx(WH_KEYBOARD_LL,keyboardproc,GetModuleHandle(“Unwindll”),0)。

LRESULT CALLBACK keyboardproc

( int code, // hook code

WPARAM wParam, // virtual-key code

LPARAM lParam // keystroke-message information

)

{

KBDLLHOOKSTRUCT *pkh = (KBDLLHOOKSTRUCT *) lParam;

if(pkh->vkCode==VK_LWIN || pkh->vkCode==VK_RWIN)

{ return 1; }

return CallNextHookEx(g_hook, code, wParam, lParam);

}

有就是对任务栏托盘图标的控制,

NOTIFYICONDATA iconnid;

iconnid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);

iconnid.hWnd=this->m_hWnd;

iconnid.uID=IDD_UNWIN_DIALOG;

iconnid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;

iconnid.uCallbackMessage=WM_SHOWTASK;//自定义的消息名称

iconnid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));

strcpy(iconnid.szTip,”屏蔽WIN键”);

Shell_NotifyIcon(NIM_ADD,&iconnid);//在托盘区添加图标

ShowWindow(SW_HIDE);//隐藏主窗口

不带MFC库的版本很小,不到7KB,有需要的朋友可以跟我联系shun5476@163.com

分类: 全部文章, 学习笔记 标签:

有关vc数据库编程

2007年4月6日 没有评论
 
研究了两天关于vc数据库编程方面的文章,还算有了点收获。一直以来有一股冲动,就是自己亲自写一个可以拿的出手的程序,然而真正动手写的时候又这也不会那也不会,就查查找找,后来就不了了之了。替就业中心管理网站系统已经很长时间了,就业中心的那个信息管理系统可谓漏洞百出,于是也早就萌发过替就业中心重新写个系统的想法,可是无能为力,只能一次又一次敷衍就业中心。
 
论实力,其实自己也是一个vc的初学者,充其量刚刚入门而已,可是凭着对计算机技术的深厚兴趣,对自己还算有信心。数据库编程技术最终会为我所运握!
分类: 全部文章, 学习笔记 标签:

vc学习:句柄和指针

2006年9月4日 没有评论

所谓句柄实际上是一个数据,是一个Long (整长型)的数据。

句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。

从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。

如果想更透彻一点地认识句柄,句柄是一种指向指针的指针。我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,我们该到哪里去找该对象呢?

为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时 (Unload)又释放给系统。

句柄地址(稳定)→记载着对象在内存中的地址────→对象在内存中的地址(不稳定)→实际对象

本质:WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。

但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理。

VC中窗口ID,句柄,指针三者相互转换函数

ID–HANDLE–HWND三者之间的互相转换
id->句柄、、、、、hWnd = ::GetDlgItem(hParentWnd,id);
id->指针、、、、、CWnd::GetDlgItem();
句柄->id、、、、、id = GetWindowLong(hWnd,GWL_ID);
句柄->指针、、、、CWnd *pWnd=CWnd::FromHandle(hWnd);
指针->ID、、、、、id = GetWindowLong(pWnd->GetSafeHwnd,GWL_ID);
指针->句柄、、、、hWnd=cWnd.GetSafeHandle() or mywnd->m_hWnd

分类: 全部文章, 学习笔记 标签:

vc学习:如何载入位图并获得位图句柄

2006年9月4日 没有评论

载入位图,通过API  函数
HBITMAP LoadBitmap( HINSTANCE hInstance, // handle to application instance
LPCTSTR lpBitmapName // address of bitmap resource name );
hInstance为应用程序的句柄为应用程序的句柄,可通过AfxGetApp()->m_hInstance获得lpBitmapName是指向位图名的指针,可通过 LPTSTR MAKEINTRESOURCE( WORD wInteger // integer to convert ); 获得,wInteger添上位图的ID..参考程序

HBITMAP bmp=::LoadBitmap(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDB_BITMAP))

分类: 全部文章, 学习笔记 标签:

VC学习:文档、视图和框架窗口间的关系和消息传送规律

2006年8月31日 没有评论

在MFC中M$引入了文档-视结构的概念,文档相当于数据容器,视相当于查看数据的窗口或是和数据发生交互的窗口。(这一结构在MFC中的OLE,ODBC开发时又得到更多的拓展)因此一个完整的应用一般由四个类组成:CWinApp应用类,CFrameWnd窗口框架类,CDocument文档类,CView视类。(VC6中支持创建不带文档-视的应用)

在程序运行时CWinApp将创建一个CFrameWnd框架窗口实例,而框架窗口将创建文档模板,然后有文档模板创建文档实例和视实例,并将两者关联。一般来讲我们只需对文档和视进行操作,框架的各种行为已经被MFC安排好了而不需人为干预,这也是M$设计文档-视结构的本意,让我们将注意力放在完成任务上而从界面编写中解放出来。

在应用中一个视对应一个文档,但一个文档可以包含多个视。一个应用中只用一个框架窗口,对多文档界面来讲可能有多个MDI子窗口。每一个视都是一个子窗口,在单文档界面中父窗口即是框架窗口,在多文档界面中父窗口为MDI子窗口。一个多文档应用中可以包含多个文档模板,一个模板定义了一个文档和一个或多个视之间的对应关系。同一个文档可以属于多个模板,但一个模板中只允许定义一个文档。同样一个视也可以属于多个文档模板。(不知道我说清楚没有)

接下来看看如何在程序中得到各种对象的指针:

全局函数AfxGetApp可以得到CWinApp应用类指针
AfxGetApp()->m_pMainWnd为框架窗口指针
在框架窗口中:CFrameWnd::GetActiveDocument得到当前活动文档指针
在框架窗口中:CFrameWnd::GetActiveView得到当前活动视指针
在视中:CView::GetDocument得到对应的文档指针
在文档中:CDocument::GetFirstViewPosition,CDocument::GetNextView用来遍历所有和文档关联的视。
在文档中:CDocument::GetDocTemplate得到文档模板指针
在多文档界面中:CMDIFrameWnd::MDIGetActive得到当前活动的MDI子窗口

一般来讲用户输入消息(如菜单选择,鼠标,键盘等)会先发往视,如果视未处理则会发往框架窗口。所以定义消息映射时定义在视中就可以了,如果一个应用同时拥有多个视而当前活动视没有对消息进行处理则消息会发往框架窗口。

分类: 全部文章, 学习笔记 标签:

VC学习日记:对话框控件访问的七种方式

2006年8月29日 没有评论

学习了孙鑫老师的视频,感悟很深,总结了一下对话框控件访问的七种方式
1. 点击静态文本改变其内容
当静态文本框需要响应消息时,许将其ID号改为不同值。首先要获取现在的静态文本框控件的文本内容:GetWindowText,其过程中,GetDlgItem:用来获取一个指定控件的指针,返回一个CWnd指针;(注意:静态文本框属性里将Notify选中,否则无法接收消息响应)void CTestDlg::OnNumber1(){ CString str; if(GetDlgItem(IDC_NUMBER1)->GetWindowText(srt),str==”Number1:”) //整个逗号表达式前半部分的值,是后半部分的值,后半部分是个判断语句。如果srt=1返回真 { GetDlgItem(IDC_NUMBER1)->SetWindowText(“数值1:”); } else { GetDlgItem(IDC_NUMBER1)->SetWindowText(“Number1:”); }}

2. GetDlgItem()->Get(Set)WindowText()将两编辑框(1,2)中输入的数字相加,在另一编辑框中显示首先要先获取编辑框1和2的内容,然后将字符内容转换为整型(atoi),相加后再itoa回字符串,显示{ int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; GetDlgItemText(IDC_EDIT1,ch1,10); GetDlgItemText(IDC_EDIT2,ch2,10); num1=atoi(ch1); num2=atoi(ch2); num3=num1+num2; itoa(num3,ch3,10); //最后一个参数10是10进制,不是num3的长度 SetDlgItemText(IDC_EDIT3,ch

3. GetDlgItemInt()/SetDlgItemInt()(可用于有/无符号数的加减){ int num1,num2,num3; num1=GetDlgItemInt(IDC_EDIT1); num2=GetDlgItemInt(IDC_EDIT2); num3=num1+num2; SetDlgItemInt(IDC_EDIT3,num3);}

4. 将控件和整型变量相关联这种方法是最简单的方法:将三个编辑框关联三个成员变量(Member Variables),用ClassWizard,Add Variable,n_num1,变量类型选为int(此时可设定变量范围)然后在OnBtnAdd()中{ UpdateData(); //模态对话框,要调用UpdateData m_num3=m_num1+m_num2; UpdateData(FALSE);}
5. 将控件和控件变量相关联控件关联控件,在ClassWizard中,增加成员变量,Category选择控件(Control){ int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; m_edit1.GetWindowText(ch1,10); //控件调用控件 m_edit2.GetWindowText(ch2,10); num1=atoi(ch1); num2=atoi(ch2); num3=num1+num2; itoa(num3,ch3,10); m_edit3.SetWindowText(ch3);}

6. SendMessage()采用发送消息,在MFC编程中几乎不用,在SDK编程中经常用到{ int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; //::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1); //::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10,(LPARAM)ch1); //关联了m_edit1,直接用 //GetDlgItem(IDC_EDIT1)->SendMessage(WM_GETTEXT,10,(LPARAM)ch1); m_edit1.SendMessage(WM_GETTEXT,10,(LPARAM)ch1); //直接利用控件变量来调用SendMessage m_edit2.SendMessage(WM_GETTEXT,10,(LPARAM)ch2); num1=atoi(ch1); num2=atoi(ch2); num3=num1+num2; itoa(num3,ch3,10); m_edit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3);}

7. SendDlgItemMessage(){ int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch1); SendDlgItemMessage(IDC_EDIT2,WM_GETTEXT,10,(LPARAM)ch2); num1=atoi(ch1); num2=atoi(ch2); num3=num1+num2; itoa(num3,ch3,10); SendDlgItemMessage(IDC_EDIT3,WM_SETTEXT,0,(LPARAM)ch3); SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,0,-1); //通过获取复选的开始和结束位置 m_edit3.SetFocus();}此时,计算结果会被自动复选上

分类: 全部文章, 学习笔记 标签:

visual c++入门:mfc窗口的创建和消息响应机制

2006年8月19日 没有评论

学了这么长时间的VC++,一直把注意力放在了VC++的核心--MFC这块了,总算用MFC捣弄出来了一个可以响应鼠标动作的小程序,可喜可贺啊,终于有了“实质性”进步了。

简单总结一下mfc窗口的创建和消息响应机制。

在MFC中,有几种典型的窗口对象,CWnd描述的一般窗口对象,CView描述的视图对象,CFrameWnd描述的SDI框窗对象,CMDIFrameWnd描述的MDI框窗对象等等。

在Window下,创建窗口可以使用两个函数,CreateWindow()和CreateWindowEx(),它们都需要一个参数,这个参数是标识窗口类的字符串。所以,如果要创建窗口,一般的做法是,先使用RegisterClass()或RegisterClassEx()注册一个窗口类,然后使用该窗口类来创建窗口。在前面我也提到过,注册窗口类的最主要目的是为系统提供窗口函数的地址,以便被DispatchMessage()之类的函数回。

在MFC中,创建窗口的函数是CWnd或其派生类的Create()或CreateEx方法,注册窗口类一般使用AfxRegisterWndClass(),在这个全局函数中,并没有发现窗口函数地址这样的参数,因此脑子里自然就会有这样的问题:窗口函数在哪里?它是如何同窗口关联的?下面我们将对MFC的一些与此有关的代码进行仔细分析,回答上述两个问题。

窗口函数:在MFC中,有一个全局的函数AfxWndProc(),正如下面的注释所示,它就是CWnd及所有从它派生的窗口类的窗口函数,它的实现如下:

// The WndProc for all CWnd's and derived classes

LRESULT CALLBACK

AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)

{

// special message which identifies the window as using AfxWndProc

if (nMsg == WM_QUERYAFXWNDPROC)

return 1

// all other messages route through message map

CWnd* pWnd = CWnd::FromHandlePermanent(hWnd)

ASSERT(pWnd != NULL)

ASSERT(pWnd->m_hWnd == hWnd)

return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam)

}

AfxCallWndProc()调用pWnd对象的虚拟函数WindowProc(),它的代码如下:

LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

// OnWndMsg does most of the work, except for DefWindowProc call

LRESULT lResult = 0

if (!OnWndMsg(message, wParam, lParam, &lResult))

lResult = DefWindowProc(message, wParam, lParam)

return lResult

}

上面的代码中,OnWndMsg()是用来处理该窗口消息的函数,如果某条消息没有被OnWndMsg()处理,也就是该窗口没有提供处理该消息的函数,它就调用DefWindowProc()进行处理,DefWindowProc()也是一个虚拟函数,看看它的代码:

LRESULT CWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)

{

if (m_pfnSuper != NULL)

return ::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam)

WNDPROC pfnWndProc

if ((pfnWndProc = *GetSuperWndProcAddr()) == NULL)

return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam)

else

return ::CallWindowProc(pfnWndProc, m_hWnd, nMsg, wParam, lParam)

}

DefWindowProc()的策略很简单,调用基类的窗口函数m_pfnSuper来处理该消息。

通过上面的分析,可以得出这样的结论:与其说AfxWndProc()是MFC的唯一窗口函数,还不如说AfxWndProc()是MFC的窗口消息分发中心。正是由于有了这个消息分发中心,才使得MFC的应用程序能够用有限的几个窗口类,作出各种形形色色的窗口,使得在应用程序中,增加CWnd的派生类,并不增加系统中窗口类的个数,将对系统资源的使用控制在一个稳定的范围之内。

注册窗口类除了提供窗口函数外,还指定该窗口的一些外观,如是否有标题条,窗口缺省背景等等。在MFC框架中,有框窗、视图和控制条(CControlBar)等,它们除了操作行为不同外,外观等也不相同,所以MFC注册了几种缺省的窗口类。在MFC中,有一个全局函数AfxEndDeferRegisterClass(LONG fToRegister),它用来注册MFC预定义的窗口类,包括同框窗、视图所对应的窗口类。由于它的代码占的篇幅很长,而且实现也很简单,所以就不列出它的代码了,如果你有兴趣,可以在wincore.cpp中找到它的实现代码。

挂接窗口函数

如果你考察过AfxEndDeferRegisterClass()的实现代码,你会对一行代码感到迷惑,下

面列出的是AfxEndDeferRegisterClass()的部分代码,带阴影部分的是那一行令人迷惑的代码:

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)

{

。。。。。。

wndcls.lpfnWndProc = DefWindowProc

。。。。。。

}

MFC将所有预定义的窗口类的窗口函数都设置成DefWindowProc。大家都知道,DefWindowProc是Window下为一般窗口提供消息缺省处理的API,它肯定不是应用程序所需要的窗口函数,所以,MFC肯定在某个地方置换了它,置换DefWindowProc的代码在哪里呢?

前面说过,在MFC中创建窗口时是用CWnd的两个虚拟函数Create()和CreateEx(),Create()是通过调用CreateEx()实现的,所以最终窗口的创建都要归结到CreateEx()函数上。因此,我们可以推断MFC在CreateEx()中置换了DefWindowProc。为了证实这一点,看看CWnd::CreateEx()的代码:

BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,

LPCTSTR lpszWindowName, DWORD dwStyle,

int x, int y, int nWidth, int nHeight,

HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)

{

// allow modification of several common create parameters

CREATESTRUCT cs

cs.dwExStyle = dwExStyle

cs.lpszClass = lpszClassName

cs.lpszName = lpszWindowName

cs.style = dwStyle

cs.x = x

cs.y = y

cs.cx = nWidth

cs.cy = nHeight

cs.hwndParent = hWndParent

cs.hMenu = nIDorHMenu

cs.hInstance = AfxGetInstanceHandle()

cs.lpCreateParams = lpParam

if (!PreCreateWindow(cs)){

PostNcDestroy()

return FALSE

}

AfxHookWindowCreate(this)

HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,

cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,

cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams)

if (!AfxUnhookWindowCreate()) PostNcDestroy(); // cleanup if CreateWindowEx fails too soon

if (hWnd == NULL) return FALSE

ASSERT(hWnd == m_hWnd); // should have been set in send msg hook

return TRUE

}

从上面的代码看不出任何显式的置换DefWindowProc的代码,其实,它隐藏在AfxHookWindowCreate(this)之中,顺藤摸瓜,再看看AfxHookWindowCreate()的代码:

void AFXAPI AfxHookWindowCreate(CWnd* pWnd)

{

_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData()

if (pThreadState->m_pWndInit == pWnd)

return

if (pThreadState->m_hHookOldCbtFilter == NULL)

{

pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,

_AfxCbtFilterHook, NULL, ::GetCurrentThreadId())

if (pThreadState->m_hHookOldCbtFilter == NULL)

AfxThrowMemoryException()

}

ASSERT(pThreadState->m_hHookOldCbtFilter != NULL)

ASSERT(pWnd != NULL)

ASSERT(pWnd->m_hWnd == NULL); // only do once

ASSERT(pThreadState->m_pWndInit == NULL); // hook not already in progress

pThreadState->m_pWndInit = pWnd

}

AfxHookWindowCreate()设置了一个线程级的CBT Hook,该Hook的入口地址为_AfxCbtFilterHook,_AfxCbtFilterHook是一个全局的MFC函数,_AfxCbtFilterHook通过调用SetWindowLong()用AfxWndProc()的入口地址置换掉DefWindowProc。

小结:在MFC中,创建一个窗口的过程是:

生成一个对应窗口类的对象

调用该对象的Create()或CreateEx()方法

在CreateEx()中(Create()是调用CreateEx()实现的),先调用虚拟函数PreCreateWindow(),让应用程序有一个改变窗口行为的机会,同时,在PreCreateWindow中,还

分类: 全部文章, 学习笔记 标签:

学习VC++之路

2006年8月12日 没有评论

其实早就想学VC++了,从学完C语言的那天就想学会C++。

期间也断断续续的看了不少关于C++的教程,却没有系统的学习,总是想一下子把200多页的东西看完,以至于很多章节都是一目十行的过了。

这两天又突然冒出一股劲,对VC++特痴迷,其实VISUAL STUDIO的软件早早就装好了,只是装过后就很少过目了。抱着做出一个自己的软件的决心开始动手了,看着软件界面,对着教程,左点右击,程序却不停的出错,真是扫兴,无奈把那些教程再一遍遍的看,一天下来已经为我的第一个程序折腾的焦头烂额了,最终还是没结果。。。

想想自己学习编程之路,自从学会了C以后,就尝试了好几种语言,网页方面的JAVASCRIPT,PHP等,狂热过一阵子的VB,还有大二时候学的VFP,学了这么多,发现到现在却是一门都不会!真是恐怖!从一次在网上听说GOOGLE的所有程序员都用C++编写程序后,更激起了学习C++的兴趣。

这次应该给自己施压了,这次一定要坚持下去,应该按照科学的方法来学,虽然以前学的那么多虽然都不成功,但多少也算点编程经验吧。

分类: 全部文章, 学习笔记 标签: