窗口对话框渐显

 

【VC++】【转】用VC实现图象渐显和渐隐
图象的渐显/渐隐是十分重要的图象效果,广泛运用于图象处理和多媒提娱乐软件。渐显/渐隐算法设计的最大困难是速度控制,包括定时和快速改变图象中各象素的颜色。如采用普通的全图扫描算法,则速度较慢,很难真正体现渐显/渐隐效果。 利用windows(3.x.95/98/nt)操作系统特殊的调色板管理和时间码定时机制能设计出有效的图象渐显/渐隐算法。windows提供一种被称为调色板动画(palette animation)的颜色处理技术,它通过快速改变颜色调色板中所选取的表项中的颜色能模拟颜色的变化。设置时间码,定时调用该技术使图象颜色渐变就能实现图象的渐显和渐隐。 一、调色板动画 在visual c++中实现调色板动画依赖于mfc类库提供的cpalette类和cdc类中的若干成员函数,其基本步骤如下: 调用cpalette::createpalette(lplogpalette lplogpalette)函数创建逻辑调色板,注意将参数lplogpalette所指向的各颜色表项结构的peflags域设置为pc_reserved,以防止其它窗口同该调色板匹配颜色。; 调用cdc::selectpalette和cdc::realizepalette函数选择和实现所创建的逻辑调色板; 调用cpalette::animatepalette函数改变颜色,实现调色板动画; 动画完成后应恢复系统调色板。 cpalette::animatepalette是其中最关键的函数,其原型如下:
  1. void animatepalette(    
  2.   
  3. uint nstartindex, // 起始的表项号    
  4.   
  5. uint nnumentries, // 变化的表项数    
  6.   
  7. lppaletteentry lppalettecolors ); // 逻辑调色板表项指针    
  8.   
  9. lppalettecolors为指向paletteentry结构的指针,其中存储着逻辑调色板将要更新的颜色信息。paletteentry结构定义如下:    
  10.   
  11. typedef struct tagpaletteentry { // pe    
  12.   
  13. byte pered;    
  14.   
  15. byte pegreen;    
  16.   
  17. byte peblue;    
  18.   
  19. byte peflags;    
  20.   
  21. } paletteentry;   
void animatepalette( uint nstartindex, // 起始的表项号 uint nnumentries, // 变化的表项数 lppaletteentry lppalettecolors ); // 逻辑调色板表项指针 lppalettecolors为指向paletteentry结构的指针,其中存储着逻辑调色板将要更新的颜色信息。paletteentry结构定义如下: typedef struct tagpaletteentry { // pe byte pered; byte pegreen; byte peblue; byte peflags; } paletteentry; void animatepalette( uint nstartindex, // 起始的表项号 uint nnumentries, // 变化的表项数 lppaletteentry lppalettecolors ); // 逻辑调色板表项指针 lppalettecolors为指向paletteentry结构的指针,其中存储着逻辑调色板将要更新的颜色信息。paletteentry结构定义如下: typedef struct tagpaletteentry { // pe byte pered; byte pegreen; byte peblue; byte peflags; } paletteentry; pered、pegreen、peblue分别表示逻辑调色板项的r、g、b颜色分量值。peflags 应被置为pc_reserved 。 nstartindex为lppalettecolors中将变化的起始表项号,nnumentries 为lppalettecolors中将变化的表项数。 二、时间码定时 cwnd::settimer函数可设置一个系统时间码,并指定每经过一定的时间间隔使windows系统发送一个wm_timer消息到窗口的消息队列中。窗口在每当接收到相应的wm_timer消息时做一定的处理,便实现了定时处理。 通常应在窗口的消息循环中接受和处理wm_timer消息,这样将很难编制通用的定时操作。通用的定时操作应将定时处理封装在一个函数中,而不与其它的代码纠缠在一起。笔者实现这一技术的技巧是,在循环操作中截获窗口消息,如消息为指定的时间码消息,则进行定时处理;否则分发消息给窗口消息处理机制。如果定时操作已结束,则修改循环标志,退出循环。具体的代码如下: ………………………………
  1. // 设置时间码,pwnd为处理定时操作的窗口对象指针    
  2.   
  3. pwnd->settimer(0x100, utimeout, null);    
  4.   
  5. // 屏蔽鼠标操作,使定时操作不受影响    
  6.   
  7. pwnd->setcapture();    
  8.   
  9. // 开始定时操作    
  10.   
  11. bool bdone = false;    
  12.   
  13. msg msg;    
  14.   
  15. while (! bdone)    
  16.   
  17. {    
  18.   
  19. if (::peekmessage(&msg, null, 0, 0, pm_remove))    
  20.   
  21. {    
  22.   
  23. if (msg.message == wm_timer && msg. wparam == 0x100)    
  24.   
  25. {    
  26.   
  27. //…………………..    
  28.   
  29. //定时操作代码    
  30.   
  31. //…………………..    
  32.   
  33. // 如定时操作完成,则设置循环标志,结束操作    
  34.   
  35. if (定时操作完成)    
  36.   
  37. bdone = true;    
  38.   
  39. }    
  40.   
  41. ::translatemessage(&msg);    
  42.   
  43. ::dispatchmessage(&msg);    
  44.   
  45. }    
  46.   
  47. }    
  48.   
  49. // 释放鼠标    
  50.   
  51. ::releasecapture();    
  52.   
  53. // 删除时间码    
  54.   
  55. pwnd->killtimer(0x100);   
// 设置时间码,pwnd为处理定时操作的窗口对象指针 pwnd->settimer(0x100, utimeout, null); // 屏蔽鼠标操作,使定时操作不受影响 pwnd->setcapture(); // 开始定时操作 bool bdone = false; msg msg; while (! bdone) { if (::peekmessage(&msg, null, 0, 0, pm_remove)) { if (msg.message == wm_timer && msg. wparam == 0x100) { //………………….. //定时操作代码 //………………….. // 如定时操作完成,则设置循环标志,结束操作 if (定时操作完成) bdone = true; } ::translatemessage(&msg); ::dispatchmessage(&msg); } } // 释放鼠标 ::releasecapture(); // 删除时间码 pwnd->killtimer(0x100); // 设置时间码,pwnd为处理定时操作的窗口对象指针 pwnd->settimer(0x100, utimeout, null); // 屏蔽鼠标操作,使定时操作不受影响 pwnd->setcapture(); // 开始定时操作 bool bdone = false; msg msg; while (! bdone) { if (::peekmessage(&msg, null, 0, 0, pm_remove)) { if (msg.message == wm_timer && msg. wparam == 0x100) { //………………….. //定时操作代码 //………………….. // 如定时操作完成,则设置循环标志,结束操作 if (定时操作完成) bdone = true; } ::translatemessage(&msg); ::dispatchmessage(&msg); } } // 释放鼠标 ::releasecapture(); // 删除时间码 pwnd->killtimer(0x100); 函数peekmessage截获窗口消息,translatemessage和dispatchmessage函数解释和分发除指定时间码消息之外的所有消息,以避免丢失消息。 三、渐显 渐显就是将显示颜色由黑色(rgb(0, 0, 0))逐渐变化为图象各象素的颜色的过程。开始时调用cpalette::getpaletteentries函数保存图象调色板的各逻辑表项信息,然后调用cpalette::setpaletteentries函数将逻辑调色板中各逻辑表项的pered、pegreen、peblue置为0,定时调用cpalette::animatepalette,每次将各逻辑表项的pered、pegreen、peblue值增加一个变化量,直到它们分别等于图象逻辑调色板中各逻辑表项的pered、pegreen、peblue值。 下面的函数fadein通过对调色板颜色表项中的各颜色分量值先设为0,然后进行递增,直到所有颜色值都恢复成原调色板中颜色值来实现渐显。
  1. // 图象渐显效果    
  2.   
  3. // 参数:    
  4.   
  5. // pwnd – 显示图象的窗口    
  6.   
  7. // ppal – 调色板指针    
  8.   
  9. // ndeta – 各颜色分量的减小量    
  10.   
  11. // utimeout – 时间的变化量    
  12.   
  13. void fadein(cwnd *pwnd, cpalette *ppal, int ndeta, uint utimeout)    
  14.   
  15. {    
  16.   
  17. // 保留原来的调色板颜色表项    
  18.   
  19. int ntotalcolors = ppal->getentrycount();    
  20.   
  21. paletteentry palettecolors0[256];    
  22.   
  23. ppal->getpaletteentries(0, ntotalcolors, palettecolors0);    
  24.   
  25. // 先将调色板表项中各颜色分量置为0    
  26.   
  27. paletteentry palettecolors1[256];    
  28.   
  29. for (int i=0; i<ntotalcolors; ++i)    
  30.   
  31. {    
  32.   
  33. palettecolors1.pered = 0;    
  34.   
  35. palettecolors1.pegreen = 0;    
  36.   
  37. palettecolors1.peblue = 0;    
  38.   
  39. palettecolors1.peflags = pc_reserved;    
  40.   
  41. }    
  42.   
  43. ppal->setpaletteentries(0, ntotalcolors, palettecolors1);    
  44. ppal->animatepalette(0, ntotalcolors, palettecolors1);    
  45.   
  46. // 设置时间码    
  47.   
  48. pwnd->settimer(0x100, utimeout, null);    
  49.   
  50. // 开始渐显    
  51.   
  52. pwnd->setcapture();    
  53.   
  54. bool bdone = false;    
  55.   
  56. msg msg;    
  57.   
  58. while (! bdone)    
  59.   
  60. {    
  61.   
  62. if (::peekmessage(&msg, null, 0, 0, pm_remove))    
  63.   
  64. {    
  65.   
  66. if (msg.message == wm_timer && msg.wparam == 0x100)    
  67.   
  68. {    
  69.   
  70. cclientdc dc(pwnd);    
  71.   
  72. cpalette *poldpal = dc.selectpalette(ppal, false);    
  73.   
  74. dc.realizepalette();    
  75.   
  76. // 递增各颜色分量    
  77.   
  78. paletteentry palettecolors[256];    
  79.   
  80. ppal->getpaletteentries(0, ntotalcolors, palettecolors);    
  81.   
  82. bool bredzero=false;    
  83.   
  84. bool bgreenzero=false;    
  85.   
  86. bool bbluezero=false;    
  87.   
  88. for (int i=0; i<ntotalcolors; ++i)    
  89.   
  90. {    
  91.   
  92. if (palettecolors.pered + ndeta <    
  93.   
  94. palettecolors0.pered)    
  95.   
  96. {    
  97.   
  98. palettecolors.pered += ndeta;    
  99.   
  100. bredzero = false;    
  101.   
  102. }    
  103.   
  104. else if (palettecolors.pered + 1 <    
  105.   
  106. palettecolors0.pered)    
  107.   
  108. {    
  109.   
  110. palettecolors.pered++;    
  111.   
  112. bredzero = false;    
  113.   
  114. }    
  115.   
  116. else    
  117.   
  118. bredzero = true;    
  119.   
  120. if (palettecolors.pegreen + ndeta <    
  121.   
  122. palettecolors0.pegreen)    
  123.   
  124. {    
  125.   
  126. palettecolors.pegreen += ndeta;    
  127.   
  128. bgreenzero = false;    
  129.   
  130. }    
  131.   
  132. else if (palettecolors.pegreen + 1 <    
  133.   
  134. palettecolors0.pegreen)    
  135.   
  136. {    
  137.   
  138. palettecolors.pegreen++;    
  139.   
  140. bgreenzero = false;    
  141.   
  142. }    
  143.   
  144. else    
  145.   
  146. bgreenzero = true;    
  147.   
  148. if (palettecolors.peblue + ndeta <    
  149.   
  150. palettecolors0.peblue)    
  151.   
  152. {    
  153.   
  154. palettecolors.peblue += ndeta;    
  155.   
  156. bbluezero = false;    
  157.   
  158. }    
  159.   
  160. else if (palettecolors.peblue +1 <    
  161.   
  162. palettecolors0.peblue)    
  163.   
  164. {    
  165.   
  166. palettecolors.peblue++;    
  167.   
  168. bbluezero = false;    
  169.   
  170. }    
  171.   
  172. else    
  173.   
  174. bbluezero = true;    
  175.   
  176. }    
  177.   
  178. // 直到恢复原始值结束    
  179.   
  180. bdone = bredzero && bgreenzero && bbluezero;    
  181.   
  182. // 使系统改变调色板    
  183.   
  184. ppal->animatepalette(0, ntotalcolors, palettecolors);    
  185.   
  186. }    
  187.   
  188. ::translatemessage(&msg);    
  189.   
  190. ::dispatchmessage(&msg);    
  191.   
  192. }    
  193.   
  194. }    
  195.   
  196. ::releasecapture();    
  197.   
  198. pwnd->killtimer(0x100);    
  199.   
  200. // 恢复原始调色板    
  201.   
  202. ppal->setpaletteentries(0, ntotalcolors, palettecolors0);    
  203.   
  204. ppal->animatepalette(0, ntotalcolors, palettecolors0);    
  205.   
  206. }   
// 图象渐显效果 // 参数: // pwnd – 显示图象的窗口 // ppal – 调色板指针 // ndeta – 各颜色分量的减小量 // utimeout – 时间的变化量 void fadein(cwnd *pwnd, cpalette *ppal, int ndeta, uint utimeout) { // 保留原来的调色板颜色表项 int ntotalcolors = ppal->getentrycount(); paletteentry palettecolors0[256]; ppal->getpaletteentries(0, ntotalcolors, palettecolors0); // 先将调色板表项中各颜色分量置为0 paletteentry palettecolors1[256]; for (int i=0; i<ntotalcolors; ++i) { palettecolors1.pered = 0; palettecolors1.pegreen = 0; palettecolors1.peblue = 0; palettecolors1.peflags = pc_reserved; } ppal->setpaletteentries(0, ntotalcolors, palettecolors1); ppal->animatepalette(0, ntotalcolors, palettecolors1); // 设置时间码 pwnd->settimer(0x100, utimeout, null); // 开始渐显 pwnd->setcapture(); bool bdone = false; msg msg; while (! bdone) { if (::peekmessage(&msg, null, 0, 0, pm_remove)) { if (msg.message == wm_timer && msg.wparam == 0x100) { cclientdc dc(pwnd); cpalette *poldpal = dc.selectpalette(ppal, false); dc.realizepalette(); // 递增各颜色分量 paletteentry palettecolors[256]; ppal->getpaletteentries(0, ntotalcolors, palettecolors); bool bredzero=false; bool bgreenzero=false; bool bbluezero=false; for (int i=0; i<ntotalcolors; ++i) { if (palettecolors.pered + ndeta < palettecolors0.pered) { palettecolors.pered += ndeta; bredzero = false; } else if (palettecolors.pered + 1 < palettecolors0.pered) { palettecolors.pered++; bredzero = false; } else bredzero = true; if (palettecolors.pegreen + ndeta < palettecolors0.pegreen) { palettecolors.pegreen += ndeta; bgreenzero = false; } else if (palettecolors.pegreen + 1 < palettecolors0.pegreen) { palettecolors.pegreen++; bgreenzero = false; } else bgreenzero = true; if (palettecolors.peblue + ndeta < palettecolors0.peblue) { palettecolors.peblue += ndeta; bbluezero = false; } else if (palettecolors.peblue +1 < palettecolors0.peblue) { palettecolors.peblue++; bbluezero = false; } else bbluezero = true; } // 直到恢复原始值结束 bdone = bredzero && bgreenzero && bbluezero; // 使系统改变调色板 ppal->animatepalette(0, ntotalcolors, palettecolors); } ::translatemessage(&msg); ::dispatchmessage(&msg); } } ::releasecapture(); pwnd->killtimer(0x100); // 恢复原始调色板 ppal->setpaletteentries(0, ntotalcolors, palettecolors0); ppal->animatepalette(0, ntotalcolors, palettecolors0); } // 图象渐显效果 // 参数: // pwnd – 显示图象的窗口 // ppal – 调色板指针 // ndeta – 各颜色分量的减小量 // utimeout – 时间的变化量 void fadein(cwnd *pwnd, cpalette *ppal, int ndeta, uint utimeout) { // 保留原来的调色板颜色表项 int ntotalcolors = ppal->getentrycount(); paletteentry palettecolors0[256]; ppal->getpaletteentries(0, ntotalcolors, palettecolors0); // 先将调色板表项中各颜色分量置为0 paletteentry palettecolors1[256]; for (int i=0; i<ntotalcolors; ++i) { palettecolors1.pered = 0; palettecolors1.pegreen = 0; palettecolors1.peblue = 0; palettecolors1.peflags = pc_reserved; } ppal->setpaletteentries(0, ntotalcolors, palettecolors1); ppal->animatepalette(0, ntotalcolors, palettecolors1); // 设置时间码 pwnd->settimer(0x100, utimeout, null); // 开始渐显 pwnd->setcapture(); bool bdone = false; msg msg; while (! bdone) { if (::peekmessage(&msg, null, 0, 0, pm_remove)) { if (msg.message == wm_timer && msg.wparam == 0x100) { cclientdc dc(pwnd); cpalette *poldpal = dc.selectpalette(ppal, false); dc.realizepalette(); // 递增各颜色分量 paletteentry palettecolors[256]; ppal->getpaletteentries(0, ntotalcolors, palettecolors); bool bredzero=false; bool bgreenzero=false; bool bbluezero=false; for (int i=0; i<ntotalcolors; ++i) { if (palettecolors.pered + ndeta < palettecolors0.pered) { palettecolors.pered += ndeta; bredzero = false; } else if (palettecolors.pered + 1 < palettecolors0.pered) { palettecolors.pered++; bredzero = false; } else bredzero = true; if (palettecolors.pegreen + ndeta < palettecolors0.pegreen) { palettecolors.pegreen += ndeta; bgreenzero = false; } else if (palettecolors.pegreen + 1 < palettecolors0.pegreen) { palettecolors.pegreen++; bgreenzero = false; } else bgreenzero = true; if (palettecolors.peblue + ndeta < palettecolors0.peblue) { palettecolors.peblue += ndeta; bbluezero = false; } else if (palettecolors.peblue +1 < palettecolors0.peblue) { palettecolors.peblue++; bbluezero = false; } else bbluezero = true; } // 直到恢复原始值结束 bdone = bredzero && bgreenzero && bbluezero; // 使系统改变调色板 ppal->animatepalette(0, ntotalcolors, palettecolors); } ::translatemessage(&msg); ::dispatchmessage(&msg); } } ::releasecapture(); pwnd->killtimer(0x100); // 恢复原始调色板 ppal->setpaletteentries(0, ntotalcolors, palettecolors0); ppal->animatepalette(0, ntotalcolors, palettecolors0); } 四、渐隐 渐隐就是将显示颜色由图象各象素的颜色逐渐变化为黑色(rgb(0, 0, 0))的过程,即定时调用cpalette::animatepalette,每次将各逻辑表项的pered、pegreen、peblue值减小一个变化量,直到它们都为0。 下面的函数fadeout通过对调色板颜色表项中的各颜色分量值进行递减,直到所有颜色值都变成0(即黑色)来实现渐隐。
  1. // 图象渐隐效果    
  2.   
  3. // 参数:    
  4.   
  5. // pwnd – 显示图象的窗口    
  6.   
  7. // ppal – 调色板指针    
  8.   
  9. // ndeta – 各颜色分量的减小量    
  10.   
  11. // utimeout – 时间的变化量    
  12.   
  13. void fadeout(cwnd *pwnd, cpalette *ppal, int ndeta, uint utimeout)    
  14.   
  15. {    
  16.   
  17. // 保留原来的调色板颜色表项    
  18.   
  19. int ntotalcolors = ppal->getentrycount();    
  20.   
  21. paletteentry palettecolors0[256];    
  22.   
  23. ppal->getpaletteentries(0, ntotalcolors, palettecolors0);    
  24.   
  25. // 设置时间码    
  26.   
  27. pwnd->settimer(0x100, utimeout, null);    
  28.   
  29. // 开始渐隐    
  30.   
  31. pwnd->setcapture();    
  32.   
  33. bool bdone = false;    
  34.   
  35. msg msg;    
  36.   
  37. while (! bdone)    
  38.   
  39. {    
  40.   
  41. if (::peekmessage(&msg, null, 0, 0, pm_remove))    
  42.   
  43. {    
  44.   
  45. if (msg.message == wm_timer && msg.wparam == 0x100)    
  46.   
  47. {    
  48.   
  49. cclientdc dc(pwnd);    
  50.   
  51. cpalette *poldpal = dc.selectpalette(ppal, false);    
  52.   
  53. dc.realizepalette();    
  54.   
  55. paletteentry palettecolors[256];    
  56. ppal->getpaletteentries(0, ntotalcolors, palettecolors);    
  57.   
  58. bool bredzero=false;    
  59.   
  60. bool bgreenzero=false;    
  61.   
  62. bool bbluezero=false;    
  63.   
  64. // 递减颜色分量    
  65.   
  66. for (int i=0; i<ntotalcolors; ++i)    
  67.   
  68. {    
  69.   
  70. if (palettecolors.pered > ndeta)    
  71.   
  72. {    
  73.   
  74. palettecolors.pered -= ndeta;    
  75.   
  76. bredzero = false;    
  77.   
  78. }    
  79.   
  80. else if (palettecolors.pered > 1)    
  81.   
  82. {    
  83.   
  84. palettecolors.pered--;    
  85.   
  86. bredzero = false;    
  87.   
  88. }    
  89.   
  90. else    
  91.   
  92. bredzero = true;    
  93.   
  94. if (palettecolors.pegreen > ndeta)    
  95.   
  96. {    
  97.   
  98. palettecolors.pegreen -= ndeta;    
  99.   
  100. bgreenzero = false;    
  101.   
  102. }    
  103.   
  104. else if (palettecolors.pegreen > 1)    
  105.   
  106. {    
  107.   
  108. palettecolors.pegreen--;    
  109.   
  110. bgreenzero = false;    
  111.   
  112. }    
  113.   
  114. else    
  115.   
  116. bgreenzero = true;    
  117.   
  118. if (palettecolors.peblue > ndeta)    
  119.   
  120. {    
  121.   
  122. palettecolors.peblue -= ndeta;    
  123.   
  124. bbluezero = false;    
  125.   
  126. }    
  127.   
  128. else if (palettecolors.peblue > 1)    
  129.   
  130. {    
  131.   
  132. palettecolors.peblue--;    
  133.   
  134. bbluezero = false;    
  135.   
  136. }    
  137.   
  138. else    
  139.   
  140. bbluezero = true;    
  141.   
  142. }    
  143.   
  144. // 如所有颜色分量都为0,则结束渐隐    
  145.   
  146. bdone = bredzero && bgreenzero && bbluezero;    
  147.   
  148. // 使系统改变调色板    
  149.   
  150. ppal->animatepalette(0, ntotalcolors, palettecolors);    
  151.   
  152. }    
  153.   
  154. ::translatemessage(&msg);    
  155.   
  156. ::dispatchmessage(&msg);    
  157.   
  158. }    
  159.   
  160. }    
  161.   
  162. ::releasecapture();    
  163.   
  164. pwnd->killtimer(0x100);    
  165.   
  166. // 恢复原始调色板    
  167.   
  168. ppal->setpaletteentries(0, ntotalcolors, palettecolors0);    
  169.   
  170. ppal->animatepalette(0, ntotalcolors, palettecolors0);   
// 图象渐隐效果 // 参数: // pwnd – 显示图象的窗口 // ppal – 调色板指针 // ndeta – 各颜色分量的减小量 // utimeout – 时间的变化量 void fadeout(cwnd *pwnd, cpalette *ppal, int ndeta, uint utimeout) { // 保留原来的调色板颜色表项 int ntotalcolors = ppal->getentrycount(); paletteentry palettecolors0[256]; ppal->getpaletteentries(0, ntotalcolors, palettecolors0); // 设置时间码 pwnd->settimer(0x100, utimeout, null); // 开始渐隐 pwnd->setcapture(); bool bdone = false; msg msg; while (! bdone) { if (::peekmessage(&msg, null, 0, 0, pm_remove)) { if (msg.message == wm_timer && msg.wparam == 0x100) { cclientdc dc(pwnd); cpalette *poldpal = dc.selectpalette(ppal, false); dc.realizepalette(); paletteentry palettecolors[256]; ppal->getpaletteentries(0, ntotalcolors, palettecolors); bool bredzero=false; bool bgreenzero=false; bool bbluezero=false; // 递减颜色分量 for (int i=0; i<ntotalcolors; ++i) { if (palettecolors.pered > ndeta) { palettecolors.pered -= ndeta; bredzero = false; } else if (palettecolors.pered > 1) { palettecolors.pered--; bredzero = false; } else bredzero = true; if (palettecolors.pegreen > ndeta) { palettecolors.pegreen -= ndeta; bgreenzero = false; } else if (palettecolors.pegreen > 1) { palettecolors.pegreen--; bgreenzero = false; } else bgreenzero = true; if (palettecolors.peblue > ndeta) { palettecolors.peblue -= ndeta; bbluezero = false; } else if (palettecolors.peblue > 1) { palettecolors.peblue--; bbluezero = false; } else bbluezero = true; } // 如所有颜色分量都为0,则结束渐隐 bdone = bredzero && bgreenzero && bbluezero; // 使系统改变调色板 ppal->animatepalette(0, ntotalcolors, palettecolors); } ::translatemessage(&msg); ::dispatchmessage(&msg); } } ::releasecapture(); pwnd->killtimer(0x100); // 恢复原始调色板 ppal->setpaletteentries(0, ntotalcolors, palettecolors0); ppal->animatepalette(0, ntotalcolors, palettecolors0); // 图象渐隐效果 // 参数: // pwnd – 显示图象的窗口 // ppal – 调色板指针 // ndeta – 各颜色分量的减小量 // utimeout – 时间的变化量 void fadeout(cwnd *pwnd, cpalette *ppal, int ndeta, uint utimeout) { // 保留原来的调色板颜色表项 int ntotalcolors = ppal->getentrycount(); paletteentry palettecolors0[256]; ppal->getpaletteentries(0, ntotalcolors, palettecolors0); // 设置时间码 pwnd->settimer(0x100, utimeout, null); // 开始渐隐 pwnd->setcapture(); bool bdone = false; msg msg; while (! bdone) { if (::peekmessage(&msg, null, 0, 0, pm_remove)) { if (msg.message == wm_timer && msg.wparam == 0x100) { cclientdc dc(pwnd); cpalette *poldpal = dc.selectpalette(ppal, false); dc.realizepalette(); paletteentry palettecolors[256]; ppal->getpaletteentries(0, ntotalcolors, palettecolors); bool bredzero=false; bool bgreenzero=false; bool bbluezero=false; // 递减颜色分量 for (int i=0; i<ntotalcolors; ++i) { if (palettecolors.pered > ndeta) { palettecolors.pered -= ndeta; bredzero = false; } else if (palettecolors.pered > 1) { palettecolors.pered--; bredzero = false; } else bredzero = true; if (palettecolors.pegreen > ndeta) { palettecolors.pegreen -= ndeta; bgreenzero = false; } else if (palettecolors.pegreen > 1) { palettecolors.pegreen--; bgreenzero = false; } else bgreenzero = true; if (palettecolors.peblue > ndeta) { palettecolors.peblue -= ndeta; bbluezero = false; } else if (palettecolors.peblue > 1) { palettecolors.peblue--; bbluezero = false; } else bbluezero = true; } // 如所有颜色分量都为0,则结束渐隐 bdone = bredzero && bgreenzero && bbluezero; // 使系统改变调色板 ppal->animatepalette(0, ntotalcolors, palettecolors); } ::translatemessage(&msg); ::dispatchmessage(&msg); } } ::releasecapture(); pwnd->killtimer(0x100); // 恢复原始调色板 ppal->setpaletteentries(0, ntotalcolors, palettecolors0); ppal->animatepalette(0, ntotalcolors, palettecolors0); -- 用VC进行屏幕截取编程 ---- 屏幕截取是令人比较感兴趣的事情.虽然现在有不少应用程序如HYPERSNAP等可以用来截取你所喜欢的屏幕画面,但是如果能把这个功能加到自己的程序中,就更能利用它强大的作用. ---- 下面用VC来逐步介绍在Windows95下的实现过程.首先我们要确定屏幕截取的区域,用LPRECT结构来定义.可以截取一个窗口,或整个屏幕.以下代码把选定的屏幕区域拷贝到位图中.
  1. HBITMAP CopyScreenToBitmap(LPRECT lpRect)    
  2. //lpRect 代表选定区域    
  3. {    
  4. HDC hScrDC, hMemDC;    
  5. // 屏幕和内存设备描述表    
  6. HBITMAP hBitmap, hOldBitmap;    
  7. // 位图句柄    
  8. int nX, nY, nX2, nY2;    
  9. // 选定区域坐标    
  10. int nWidth, nHeight;    
  11. // 位图宽度和高度    
  12. int xScrn, yScrn;    
  13. // 屏幕分辨率    
  14.   
  15. // 确保选定区域不为空矩形    
  16. if (IsRectEmpty(lpRect))    
  17. return NULL;    
  18. //为屏幕创建设备描述表    
  19. hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);    
  20. //为屏幕设备描述表创建兼容的内存设备描述表    
  21. hMemDC = CreateCompatibleDC(hScrDC);    
  22. // 获得选定区域坐标    
  23. nX = lpRect- >left;    
  24. nY = lpRect- >top;    
  25. nX2 = lpRect- >right;    
  26. nY2 = lpRect- >bottom;    
  27. // 获得屏幕分辨率    
  28. xScrn = GetDeviceCaps(hScrDC, HORZRES);    
  29. yScrn = GetDeviceCaps(hScrDC, VERTRES);    
  30. //确保选定区域是可见的    
  31. if (nX 〈0)    
  32. nX = 0;    
  33. if (nY 〈 0)    
  34. nY = 0;    
  35. if (nX2 > xScrn)    
  36. nX2 = xScrn;    
  37. if (nY2 > yScrn)    
  38. nY2 = yScrn;    
  39. nWidth = nX2 - nX;    
  40. nHeight = nY2 - nY;    
  41. // 创建一个与屏幕设备描述表兼容的位图    
  42. hBitmap = CreateCompatibleBitmap    
  43. (hScrDC, nWidth, nHeight);    
  44. // 把新位图选到内存设备描述表中    
  45. hOldBitmap = SelectObject(hMemDC, hBitmap);    
  46. // 把屏幕设备描述表拷贝到内存设备描述表中    
  47. BitBlt(hMemDC, 0, 0, nWidth, nHeight,    
  48. hScrDC, nX, nY, SRCCOPY);    
  49. //得到屏幕位图的句柄    
  50. hBitmap = SelectObject(hMemDC, hOldBitmap);    
  51. //清除    
  52. DeleteDC(hScrDC);    
  53. DeleteDC(hMemDC);    
  54. // 返回位图句柄    
  55. return hBitmap;    
  56. }    
  57.   
  58. 得到屏幕位图句柄以后,我们    
  59. 可以把屏幕内容粘贴到剪贴板上.    
  60. if (OpenClipboard(hWnd))    
  61. //hWnd为程序窗口句柄    
  62. {    
  63. //清空剪贴板    
  64. EmptyClipboard();    
  65. //把屏幕内容粘贴到剪贴板上,    
  66. hBitmap 为刚才的屏幕位图句柄    
  67. SetClipboardData(CF_BITMAP, hBitmap);    
  68. //关闭剪贴板    
  69. CloseClipboard();    
  70. }    
  71. 我们也可以把屏幕内容以位图格式存到磁盘文件上.    
  72.   
  73. int SaveBitmapToFile(HBITMAP hBitmap ,    
  74. LPSTR lpFileName) //hBitmap 为刚才的屏幕位图句柄    
  75. //lpFileName 为位图文件名    
  76. HDC hDC;    
  77. //设备描述表    
  78. int iBits;    
  79. //当前显示分辨率下每个像素所占字节数    
  80. WORD wBitCount;    
  81. //位图中每个像素所占字节数    
  82. //定义调色板大小, 位图中像素字节大小 ,    
  83. 位图文件大小 , 写入文件字节数    
  84. DWORD dwPaletteSize=0,    
  85. dwBmBitsSize,    
  86. dwDIBSize, dwWritten;    
  87. BITMAP Bitmap;    
  88. //位图属性结构    
  89. BITMAPFILEHEADER bmfHdr;    
  90. //位图文件头结构    
  91. BITMAPINFOHEADER bi;    
  92. //位图信息头结构    
  93. LPBITMAPINFOHEADER lpbi;    
  94. //指向位图信息头结构    
  95. HANDLE fh, hDib, hPal,hOldPal=NULL;    
  96. //定义文件,分配内存句柄,调色板句柄    
  97.   
  98. //计算位图文件每个像素所占字节数    
  99. hDC = CreateDC("DISPLAY",NULL,NULL,NULL);    
  100. iBits = GetDeviceCaps(hDC, BITSPIXEL) *    
  101. GetDeviceCaps(hDC, PLANES);    
  102. DeleteDC(hDC);    
  103. if (iBits 〈 = 1)    
  104. wBitCount = 1;    
  105. else if (iBits 〈 = 4)    
  106. wBitCount = 4;    
  107. else if (iBits 〈 = 8)    
  108. wBitCount = 8;    
  109. else if (iBits 〈 = 24)    
  110. wBitCount = 24;    
  111. //计算调色板大小    
  112. if (wBitCount 〈 = 8)    
  113. dwPaletteSize = (1 〈 〈 wBitCount) *    
  114. sizeof(RGBQUAD);    
  115.   
  116. //设置位图信息头结构    
  117. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);    
  118. bi.biSize = sizeof(BITMAPINFOHEADER);    
  119. bi.biWidth = Bitmap.bmWidth;    
  120. bi.biHeight = Bitmap.bmHeight;    
  121. bi.biPlanes = 1;    
  122. bi.biBitCount = wBitCount;    
  123. bi.biCompression = BI_RGB;    
  124. bi.biSizeImage = 0;    
  125. bi.biXPelsPerMeter = 0;    
  126. bi.biYPelsPerMeter = 0;    
  127. bi.biClrUsed = 0;    
  128. bi.biClrImportant = 0;    
  129.   
  130. dwBmBitsSize = ((Bitmap.bmWidth *    
  131. wBitCount+31)/32)* 4    
  132. *Bitmap.bmHeight ;    
  133. //为位图内容分配内存    
  134. hDib = GlobalAlloc(GHND,dwBmBitsSize+    
  135. dwPaletteSize+sizeof(BITMAPINFOHEADER));    
  136. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);    
  137. *lpbi = bi;    
  138. // 处理调色板    
  139. hPal = GetStockObject(DEFAULT_PALETTE);    
  140. if (hPal)    
  141. {    
  142. hDC = GetDC(NULL);    
  143. hOldPal = SelectPalette(hDC, hPal, FALSE);    
  144. RealizePalette(hDC);    
  145. }    
  146. // 获取该调色板下新的像素值    
  147. GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight,    
  148. (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)    
  149. +dwPaletteSize,    
  150. (BITMAPINFOHEADER *)    
  151. lpbi, DIB_RGB_COLORS);    
  152. //恢复调色板    
  153. if (hOldPal)    
  154. {    
  155. SelectPalette(hDC, hOldPal, TRUE);    
  156. RealizePalette(hDC);    
  157. ReleaseDC(NULL, hDC);    
  158. }    
  159. //创建位图文件    
  160. fh = CreateFile(lpFileName, GENERIC_WRITE,    
  161. 0, NULL, CREATE_ALWAYS,    
  162. FILE_ATTRIBUTE_NORMAL | FILE_    
  163. FLAG_SEQUENTIAL_SCAN, NULL);    
  164. if (fh == INVALID_HANDLE_VALUE)    
  165. return FALSE;    
  166. // 设置位图文件头    
  167. bmfHdr.bfType = 0x4D42; // "BM"    
  168. dwDIBSize = sizeof(BITMAPFILEHEADER)    
  169. sizeof(BITMAPINFOHEADER)    
  170. + dwPaletteSize + dwBmBitsSize;    
  171. bmfHdr.bfSize = dwDIBSize;    
  172. bmfHdr.bfReserved1 = 0;    
  173. bmfHdr.bfReserved2 = 0;    
  174. bmfHdr.bfOffBits = (DWORD)sizeof    
  175. (BITMAPFILEHEADER)    
  176. + (DWORD)sizeof(BITMAPINFOHEADER)    
  177. + dwPaletteSize;    
  178. // 写入位图文件头    
  179. WriteFile(fh, (LPSTR)&bmfHdr, sizeof    
  180. (BITMAPFILEHEADER), &dwWritten, NULL);    
  181. // 写入位图文件其余内容    
  182. WriteFile(fh, (LPSTR)lpbi, dwDIBSize,    
  183. &dwWritten, NULL);    
  184. //清除    
  185. GlobalUnlock(hDib);    
  186. GlobalFree(hDib);    
  187. CloseHandle(fh);   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值