|
|
2008年2月26日
(1)将窗口设为顶层窗口:
c++:
//[注意]:BringWindowToTop( hwnd )不会使窗口成为TopMost窗口!
SetWindowPos(hDlg,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE); //忽略x,y,cx,cy参数
c#:
form1.TopMost=true;
(2)设置窗口透明度:
(未完待续)
BalloonTip通常出现在位于屏幕右下角的Tray(成为通知栏,或系统托盘)的Icon上,比如用户插拔USB设备时的气泡提示。该函数位于Shell32中,是通过调用下面这个API函数实现的, BOOL Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA lpdata ); 该函数用于控制对TrayIcon进行控制,可以弹出BalloonTip。然后却只能局限于Tray位置。而在QQ的聊天对话框中,我们发现如果不输入内容而试图发送消息时,就会在按钮上弹出这样的Tip。为此,我在C#中写了一个类似的窗口,可以在任意位置浮出,效果如下:
这是测试程序的截图。在实现时,略微参考了codeproject上的仿MSN浮出窗口的代码。其涉及的主要麻烦是,为了提供足够灵活的接口,应该如何处理窗口上各个元素布局。为了简单期间,这里仅仅提供了“箭头”位于右下角的布局方式。(很显然该箭头一共可以有8个停靠位置)。
(1)在弹出时,不夺走其他窗口焦点。为此使用了API的ShowWindow函数: ShowWindow(this.Handle, SW_SHOWNOACTIVATE);
(2)窗体上一共包含4项主要内容:图标,标题,内容文本,关闭按钮。用户可以配置他们,例如选择图标(可以由外部设置或者使用内置图标),是否显示关闭按钮,是否自动关闭(如果把TimeoutMilliSeconds属性设为负数则不会自动关闭,只能通过CloseButton关闭),各种颜色,字体等。另提供一个BalloonClick事件,通知外部用户点击事件。
(3)绘制CloseButton的位图时,由于图中具有透明色,因此需要在绘制时指定透明色,相当于蒙版的作用。否则透明色会被绘制到窗体上导致窗体透明那个。
(4)弹出该窗口,主要使用ShowAt()函数。里面需要一些参数。如果需要进一步设置其他属性,可以单独进行设置。
源代码的下载链接:
http://www.cnblogs.com/Files/hoodlum1980/JDL.UILib_BalloonTip_VS7.rar
编译器提示:warning treated as error,然后某个文件未生成,build中断。
这是因为项目选项中把warning级别设置为了较高的级别导致的,某些warning被当作error,从而不能生成。
解决方法是在解决方案窗口中选中项目,右键点击project,选择“属性”,在弹出的对话框中,选择左侧TreeView中的“Configuration Properties”->“C/C++l”->“General”节点,在右侧有“Treat Warnings As Errors”(将警告当作错误对待)选项。我们把该项该为NO即可。即把相应命令行的"/WX"改为"/W"。
相应的编译选项如下:(参考MSDN)
/w 禁止所有警告
/Wn 指定显示的最高等级警告。有效等级是0~4。0级禁止所有警告。4级显示所有警告。
/Wall 使能所有警告。
/WX 视所有警告为错误。
/wln 将某个指定警告视为某个级别。第一个参数是新的级别,第二个参数是警告号码。例如/w14326 使 C4326成为1级警告。
/wdn 禁止某特定警告。n是警告号。例如, /wd4326 禁止C4326警告。
/wen 将某个指定警告视为错误。n是警告号。例如, /we4326 把 C4326 视为错误。
/won 某警告仅仅报告一次。例如:wo4326使C4326仅仅报告一次。
摘要: 摘要: 最近有感于部分网友对高斯模糊滤镜的研究,本文将对高斯模糊中半径值的含义以及高斯模糊模板尺寸的疑惑做出总结和解答。 阅读全文
摘要: 在上一篇文章中,我们介绍了开发Photoshop滤镜插件最基本的一些概念和基础。Ps为了满足插件的应用需求,同时也给插件提供了大量的回调函数(或服务)。例如,滤镜可以在一次调用后,保存最近一次用户设置的参数,并应用到下次调用或显示UI。这就是通过Ps的回调函数完成的。这一篇文章我们将讲解最重要的一些Ps回调函数。了解本文之后,我们将能够使用回调函数,完成例如存储我们的滤镜参数等必要的工作。本篇文章将比第一篇复杂和深入的多,但同时从这篇文章我们也可以一窥PS内部的秘密:缜密的系统设计,完善的接口以及复杂的工作机制。 阅读全文
摘要: 在flyweight模式,指的是具有大量的轻量级对象,我们为这些对象建立一个实体对象,其他则为“虚像”或者称为对该实体的一种“引用”。在我从前的项目中,电力系统的矢量图中,有大量设备,同种类型设备采用一种符号绘制,称为图元。这里就属于一中flyweight模式应用。...... 阅读全文
摘要: Photoshop是数字图像处理的杰出软件。他允许第三方以插件形式扩展功能。本文讲解用户最为熟悉的Photoshop滤镜插件的开发,以一个水滴效果滤镜为实例,主要介绍滤镜插件的开发流程,讨论了一些比较重要的相关技术细节问题。 阅读全文
题目链接: http://acm.zju.edu.cn/show_problem.php?pid=1146
这是一道用于把数字显示成LCD样子的题目,输入每一行有两个整数,第一个整数n表示笔画大小,第二个是需要显示成LCD样子的数字。这道题没有什么太难的,但是却让我在输出格式上卡住了,始终是Presentation Error,让我百思不得其解。后来我才发现原来是因为题目叙述的不够精确,使我没有准确理解输出格式的要求,导致我每一行都多输出了一个结尾空格。找到问题后,当然立刻就AC了。代码也不具备什么含量。
由于没有什么难度的地方,并且我也加了一点点注释,所以就没什么可做更多叙述的了。这只是一道比较简单的题目,但是输出格式一定要正确理解。
 ZOL 1146 CODE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void PrintVer(int,int,char*);
void PrintHor(int,int,char*);
void PrintNumbers(int,char*);
/*LCD的字型码*/
/* -0-
1 2
-3-
4 5
-6-
*/
int LCDCODES[10][7]=
{
{1,1,1,0,1,1,1},/*0*/
{0,0,1,0,0,1,0},/*1*/
{1,0,1,1,1,0,1},/*2*/
{1,0,1,1,0,1,1},/*3*/
{0,1,1,1,0,1,0},/*4*/
{1,1,0,1,0,1,1},/*5*/
{1,1,0,1,1,1,1},/*6*/
{1,0,1,0,0,1,0},/*7*/
{1,1,1,1,1,1,1},/*8*/
{1,1,1,1,0,1,1} /*9*/
};
char c_ver='|';
char c_hor='-';
/* 两个相邻字母中间隔了一个空列 ,因此平均每个字母占据n+3列,最后一列为间隔*/
/*打印竖直笔画,n-笔画长度,section=1或者4,numbers-数字字符串*/
void PrintVer(int n,int section,char *numbers)
{
char *line;
int i,len=(n+3)*strlen(numbers);
line=(char*)malloc(len+1);
if(line==NULL)
return;
memset(line,' ',len);
for(i=0;i<strlen(numbers);i++)
{
if(LCDCODES[*(numbers+i)-'0'][section])
*(line+(n+3)*i)=c_ver;
if(LCDCODES[*(numbers+i)-'0'][section+1])
*(line+(n+3)*i+(n+1))=c_ver;
}
/*检查最后一个字符,如果没有笔画,要使\0前移2格!*/
line[len-1]='\0';
/*打印n行*/
for(i=0;i<n;i++)
printf("%s\n",line);
free(line);
}
/*打印水平笔画,n-笔画长度,section=0,3,or 6,numbers-数字字符串*/
void PrintHor(int n,int section,char *numbers)
{
char *line;
int i,len=(n+3)*strlen(numbers);
line=(char*)malloc(len+1);
if(line==NULL)
return;
memset(line,' ',len);
for(i=0;i<strlen(numbers);i++)
{
if(LCDCODES[*(numbers+i)-'0'][section])
memset((line+(n+3)*i+1),c_hor,n);
}
/*注意最后一个数字后面无需空格了!所以多缩进一个位置*/
line[len-1]='\0';
/*打印1行*/
printf("%s\n",line);
free(line);
}
/* Print A set of Numbers : "23456" e.g. */
void PrintNumbers(int n,char *numbers)
{
PrintHor(n,0,numbers); /* ---- */
PrintVer(n,1,numbers); /* | | */
PrintHor(n,3,numbers); /* ---- */
PrintVer(n,4,numbers); /* | | */
PrintHor(n,6,numbers); /* ---- */
}
int main()
{
char line[20];
char *str1,*numbers,*delim=" ";
int n;
do
{
gets(line);
str1=strtok(line,delim);
numbers=strtok(NULL,delim);
n=atoi(str1);
if(n<=0)
break;
PrintNumbers(n,numbers);
/*每两行数字之间有一个空行*/
printf("\n");
}
while(1);
}
/*--------------------------------------------------
打印后正确的输出格式应该类似下面这样:(@表示行尾)
- - - - @
| | | | | | | | @
- - - - @
| | | | | | |@
- - - - @
----------------------------------------------------*/
这道题目:http://acm.zju.edu.cn/show_problem.php?pid=1113 的大意如下:根据公式
e=1/0!+1/1!+1/2!+1/3!+...+1/n!
计算e。要求输出需要的小数位数(9位)。
题目很直观,最直观的想法可能是一个计算n!的函数,然后一个从0到n的循环,累加所有的小数。不过这样做显然会有很多冗余计算。为了避免这种情况,显然,
假设a[n]表示1/n!,e[n]表示e,则
a[n+1]=a[n]/(n+1);
e[n+1]=e[n]+a[n+1];
根据这个等式,我们可以写出解答方法。由于题目中要求小数精度,也许随着计算机位数的增长,double能够满足精度。但是在16位的TC下似乎是无法满足的,所以考虑用大数方法处理小数。即使用一个数组a[]表示小数部分。(这里假设小数具有0.********的形式),按照这个处理方法的惯例,我们规定,
a[0]表示小数的数据位数,a[i] (i>0)中存放第i位小数的数字。例如PI 3.1415926,它的小数部分可以用下面的数组表示:
{7,1,4,1,5,9,2,6,0,0,0,........};
那么这个小数就可以表示成
a[1]*10^(-1)+a[2]*10^(-2)+...+a[n]*10^(-n)
由于
a * 10^(-i) + (10*b + c) * 10^(-(i+1)) = (a+b) * 10^(-i) + c * 10 ^(-(i+1))
所以,相邻位之间以此规则进位或者退位以及规整。
根据上面的迭代式子,我们看到至少两种小数运算,一个是小数除以整数,一个是两个小数相加。在这个题目中实际上精度不高,因此对代码执行效率的要求可以降低,但是为了通用,我还是保持该算法的惯用风格。
下面,给出一个小数除以一个整数的代码,由于一个已经规整过的小数这样运算的时候,不可能出现大于10的结果,所以这时我们无需对结果进行规整处理。
 一个小数除以一个整数
#define DISLEN 9 /*最多小数位数*/
#define TOTLEN 13 /*总长度,即显示小数位数+冗余的小数位数*/
/*计算一个0.--的小数除以一个整数后的小数。*/
void Devide(int a[],int n)
{
int i,temp;/*余数*/
for(i=1; i<=a[0] && i<(TOTLEN-1); i++)
{
temp=a[i]%n; /*先保存余数!!!不能先改变a[i],切记!*/
a[i]=a[i]/n;
a[i+1]+=temp*10;
if(i==a[0] && temp!=0)
a[0]=i+1;
}
/*对最后一位进行除法运算*/
a[TOTLEN-1]/=n;
}
由于结果需要四舍五入,所以实际上我给出了一些冗余位,以保持四舍五入时候的结果正确。
下面是两个小数相加的运算代码,即a=a+b,结果是a被改变为两者的和,b不发生变化。在a的基础上改动,可以使我们节省空间。相对而言,大数相加减的代码是最为简单直观的。
 两个小数相加
/*注意两个正小数相加,他们的最大位数只可能减少,不可能增加!*/
void Add(int a[],int b[])
{
int i;
a[0]=MAX(a[0],b[0]);
for(i=1;i<=a[0];i++)
{
a[i]+=b[i];
}
/*规整小数*/
formular(a);
}
/*加法后的规整小数*/
void formular(int a[])
{
int i;
for(i=a[0];i>1;i--)
{
a[i-1]+=a[i]/10;
a[i]=a[i]%10;
}
a[1]=a[1]%10;
/*当最后一位为0时,位数递减(缩减位数)*/
while(!a[a[0]] && a[0])
{
a[0]--;
}
}
注意,两个小数相加以后,可能产生结果在某些位大于10,因此这时需要一次规整运算。
最后,我们还需要对数组进行一次扫描,输出四舍五入后的结果:由于我们的目的是计算e,因此整数部分是确定的“2.”。
 输出四舍五入后的结果值
/*输出e的小数表示,用2.开始,e[]中是小数部分*/
void OutputE(int a[])
{
/*len表示四舍五入后的小数长度,flag表示是否进位!*/
int i,len,flag;
printf("2.");
/*对最后一位进行四舍五入!如果位数不大于DISLEN说明无需四舍五入*/
len=DISLEN+1;
if(a[len]>4)
{
flag=1;
while(a[--len]==9);
}
else
{
flag=0;
while(a[--len]==0);
}
/*打印前几个字符*/
for(i=1;i<len;i++)
printf("%d",a[i]);
/*根据是否进位,打印最后一个数字*/
if(len>0)
printf("%d",flag? (a[len]+1):a[len]);
for(i=len+1;i<=DISLEN;i++)
printf("0");
printf("\n");
}
最后我们给出迭代部分的代码,由于使用迭代式,因此下一步的计算建立在前一步的计算结果的基础上,这样就避免了冗余计算。
 迭代E的结果
int e[TOTLEN],a[TOTLEN];
/* e2=2.5, a2=0.5 */
e[0]=a[0]=1;
e[1]=a[1]=5;
for(j=3;j<=9;j++)
{
Devide(a,j); /*a[n+1]=a[n]/(n+1);*/
Add(e,a); /*e[n+1]=e[n]+a[n+1];*/
printf("%d ",j);
OutputE(e);
}
当我们想要输出80位小数时,结果如下(显然可以直接运算的内部数据类型是无法达到这样精度的):
2.71828182845904523536028747135266249775724709369995957496696762772407663035354759
|