返回列表 发帖

【教学视频】《C语言也能干大事》第八节:控件基本操作、回调及自己动手写小时钟

《C语言也能干大事》已经录制第二版,不推荐初学者学习这里的旧版,因此请到下面的地址( http://www.rupeng.com/forum/forum-52-1.html )学习第二版。

在线观看视频(非清晰在线版):


清晰版下载
如鹏下载站1:点击下载
如鹏电骡(verycd)下载站:http://www.verycd.com/topics/2800166/

板书:
接下来我们要实现小时钟。涉及到的主要知识点是定时器的使用,涉及到的C知识就是函数指针(回调函数)
使用定时器
回调就是不是你调别人,而是别人调你。
Windows直接将定时器消息发送给您程序的另一个函数。
我们把以下的callback函数称为TimerProc(您能够选择与其它一些用语不会发生冲突的任何名称),它只处理WM_TIMER消息:
VOID CALLBACK TimerProc (
HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime);


SetTimer (hwnd, iTimerID, iMsecInterval, TimerProc) ;
定时器还有其他两种用法,大家可以参考《Windows》程序设计这本书(不想变成填鸭式教育,课上只讲思想性的东西,会给大家学习资料,希望大家培养自学能力)

19、得到当前日期:
void GetLocalTime(LPSYSTEMTIME);
课上练习:

SYSTEMTIME stLocal;


char chBuf[256];


GetLocalTime(&stLocal);


//
显示时间的间隔。

wsprintf(chBuf,TEXT("%u/%u/%u %u:%u:%u:%u
%d\r\n"),



stLocal.wYear, stLocal.wMonth, stLocal.wDay,



stLocal.wHour, stLocal.wMinute, stLocal.wSecond,



stLocal.wMilliseconds,stLocal.wDayOfWeek);


MessageBox(NULL,chBuf,"",MB_OK);


SetTimer(hwnd,1,1000,TimerProc);

void CALLBACK TimerProc (HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)
{

SYSTEMTIME time;


GetLocalTime(&time);


TCHAR strTime[256];


//%
后面的0表示不够的位数补零,5是总位数,就这样

wsprintf(strTime,"%04d-%02d-%02d %02d:%02d:%02d",time.wYear,time.wMonth,time.wDay,time.wHour,time.wMinute,time.wSecond);


SetDlgItemText(hwnd,IDC_EDTTIME,strTime);

}

后续的课程会讲得到空余内存、硬盘信息(总大小、空余、类型)、得到当前登录用户名、得到操作系统类型→自己动手写windows优化大师1.0
菜单、文件处理、windows控件的操作→自己动手写记事本






有人说了“干嘛知道这么多?使用C#VBDelphi之类的工具拖拽控件,像搭积木一样就可以搭建出一个程序来”。确实如此,但是这样的程序员恐怕竞争力不强。只有深入了解内部原理,才能让自己对技术融会贯通,也才能让程序员之路走得更稳健、更长久。永远记住价值规律:越容易的东西越便宜。
6)句柄(Handle,注意这个概念后面要经常用到,需要仔细理解)
         句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例、窗口、图片、图标等等。WINDOWS句柄有点象C语言中的文件句柄。在运行时唯一确定一个对象!

         为什么要搞句柄这个东西呢?比如我们要加载一个图片,这时就要调用系统的加载图片的API函数,API函数会将图片加载到内存的一个区域,然后通过什么方式将这个区域的地址告诉调用者呢?有的同学会说:直接将内存区域的指针返回不就行了吗?对于图片、文件等对象来说,分配到堆!而不是栈!存在下面的问题:这些对象并不是立即被加载到内存的,只有访问到的时候才加载到内存中;为了高效的利用内存,操作系统可能会移动数据在内存中的位置。因此不能直接返回内存的指针,操作系统会为这个图片、文件对象分配一个唯一的标识号,然后就可以按照这个标识号进行资源的访问了。这个标识号就是句柄,句柄其实就是一个对象的编号,数据类型其实就是整数,只不过用typedef搞了一个别名而已。
怎么得到控件句柄呢?根据id得到。

消息机制、回调函数和函数指针(现在明白C程序设计中的函数指针是做什么用的了吧)

控件句柄和控件id的区别:控件句柄在每次运行的时候都是不一样的,而控件id则是确定的;就像fopen函数返回的句柄一样,每次运行的句柄都不是一样的,但是文件名是确定的。
句柄一般在运行时动态根据id算出来。

hFile = fopen("c:/a.txt")

5、设置、读取控件的文字(文本框、标签、CheckBoxButton
设置:
方法1SetDlgItemText(hwnd,IDC_EDTNAME,TEXT("世界你好"));
方法2 HWND hwndEdtName = GetDlgItem(hwnd,IDC_EDTNAME);

SetWindowText(hwndEdtName,TEXT("
世界你好"));
读取:
方法1


HWND hwndEdtName = GetDlgItem(hwnd,IDC_EDTNAME);



TCHAR str[256];



ZeroMemory(str,sizeof(str));



GetWindowText(hwndEdtName,str,sizeof(str));


MessageBox(hwnd,str,"",MB_OK);

方法2


TCHAR str[256];



ZeroMemory(str,sizeof(str));


GetDlgItemText(hwnd,IDC_EDTNAME,str,sizeof(str));


MessageBox(hwnd,str,"",MB_OK);

SetDlgItemTextGetDlgItemSetWindowText的关系
我在家里是老大,所以别人要打我的话有两种方式:
1、直接找到我,然后打我。这就是直接抓住我的把柄SetWindowText
2、找到我爸,然后找我爸爸的id=1的儿子,也就是我,然后再打我。这就是通过我把的把柄和我的id=1来定义我
SendDlgItemMessageSendMessage一个道理。

3、可以使用GetDlgCtrlID来根据控件句柄得到控件的ID,也可以使用GetDlgItem (hwndParent, id)来根据控件的id得到控件的句柄。函数中的「Dlg」部分指的是对话框,但实际上这是一个通用的函数。

今天看到这里,留个言,哈哈,谢谢老师,都是在visual studio 2005上转换老师的东西,转换的过程很爽,很暴力。。
顺便说下,老师在编辑框里面加数字不比先用itoa转换然后才用GetDlgItemText(),还有个函数的GetDlgItemInt(),在2005上没有问题了,不知道Cfree上的情况,应该也差不多吧~杨老师加油!!
1

评分人数

TOP

坐个沙发学习!

TOP

坐个沙发学习!

TOP

什么时候才上下一课啊,

TOP

反过头来,才发现讲的都用到了!!!

TOP

每看完一节课,感激之情油然而生
提醒自己   08年6月30日开始自学C

TOP

比看书明白多了,

TOP

代码

这个有 代码么。  自己的错误不知道从哪下手【- -。  麻烦传个 代码

TOP

还有一个小问题就是,初始化对话框的时候有个SetTimer(),在对话框刚启动的时候是不调用On_Time()函数的,有一秒的延迟,所以就出现了,刚打开对话框的时候是没显示时间的,所以我觉得在初始化的时候就应该先打印一次时间,后面再由On_Time()函数更新时钟

TOP

做了个小时钟,仿照老师的方法。
BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
    // Set app icons
    HICON hIcon = LoadIcon((HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE) ,MAKEINTRESOURCE(IDI_ICONAPP));
    SendMessage(hwnd, WM_SETICON, TRUE,  (LPARAM)hIcon);
    SendMessage(hwnd, WM_SETICON, FALSE, (LPARAM)hIcon);
    SetTimer(hwnd,1,1000,On_timer); //最后一个是函数的指针,其实就是函数名
    SetTimer(hwnd,2,1000,On_timer2);
    //
    // Add initializing code here
    //
   
    return TRUE;
}
void CALLBACK On_timer(HWND hwnd,UINT Message,UINT iTimer,DWORD dTimer)
{
   SYSTEMTIME sTime;
   TCHAR cResult[256];
   GetLocalTime(&sTime);
   wsprintf(cResult,TEXT("%04d:%02d:%02d  %02d:%02d:%02d"),sTime.wYear,sTime.wMonth,sTime.wDay
                     ,sTime.wHour,sTime.wMinute,sTime.wSecond);
   SetDlgItemText(hwnd ,IDC_EDTTIME,cResult);
}
void CALLBACK On_timer2(HWND hwnd,UINT Message,UINT iTimer,DWORD dTimer)
{
   SYSTEMTIME sTime;
   TCHAR cResult[256];
   GetLocalTime(&sTime);
   wsprintf(cResult,TEXT("%04d年%02d月%02d日  %02d时%02d分%02d秒"),
   sTime.wYear,sTime.wMonth,sTime.wDay,sTime.wHour,sTime.wMinute,sTime.wSecond);
   SetDlgItemText(hwnd,IDC_EDT1,cResult);
}
clock.jpg

MYclock2.rar (20.71 KB)

TOP

一点小疑问

1 . 老大在讲定义结构体指针的时候,第一遍是故意出错的吧?是不是想让我们看看系统是怎么定义的啊?
我看视频的时候觉得有点不可思议,这样的错误太低级了吧,定义MyStruct 的时候大括号后面少了个分号应该一眼就看出来了。

2 .老大在讲wsprintf 函数的时候说“%xxd”中第一个“x”是补什么数,第二个“x ”是补多少位。貌似这样的解释有问题吧?
%xxd 我理解的意思是:假如第一个x不是0的话,就表示输出字符的宽度为xx位,如果数据的位数小于xx,则左端补以空格。
若第一个字符是0,则表示输出字符的宽度为x位,如果数据的位数小于x,则左端补以0.

不知道这样的理解对不对,不到之处,敬请老大原谅!

TOP

帮我看看

不知道怎么让日期也随着动起来。

clock.rar (18.42 KB)

TOP

顶  学习   学习

TOP

飘过,学习学习,

TOP

学习了,呵呵。
Now!Acting!

TOP

谢谢老师,帮助很大

TOP

API真好玩

TOP

好教程啊!!刷点分下载吧好教程啊!!刷点分下载吧

TOP

好教程啊!!刷点分下载吧

TOP

好教程  好好学一下

TOP

好好学一下

TOP

用工具编出来东西,而不懂框架底层的原理,这中程序员是武前途可言的。杨老师的这套对我帮助太大了,谢谢您。支持杨老师

TOP

呵呵 刚看完第一节 挺好玩

TOP

老大辛苦了,偶也来顶一个,有新的我还会在来的

TOP

想学 但是没钱啊  

TOP

恩那    同感     新手 !!!    渴望!!

TOP

下不了啊  很想下  给个资源吧

TOP

返回列表