原文地址::http://www.devdiv.net/viewthread-8326
原帖地址::http://www.devdiv.net/bbs/viewthread.php?tid=8326&extra=&page=1
现在有三张图片,希望可以将其做为一个长方体的可见的三个面。
我的思路是,将这三张图片分别打印到三个DC上,然后对这三块DC进行操作,但是对Windows编程了解太少,不知如何下手。
向诸位请教了。
我的思路是,将这三张图片分别打印到三个DC上,然后对这三块DC进行操作,但是对Windows编程了解太少,不知如何下手。
向诸位请教了。
CODE:
/// <summary>
{/// 画矩形体
/// </summary>
/// <param name="x">矩形体最外面的矩形的左上角x坐标</param>
/// <param name="y">矩形体最外面的矩形左上角y坐标</param>
/// <param name="width">矩形最外面的矩形宽</param>
/// <param name="length">矩形顶部面的矩形长</param>
/// <param name="height">矩形最外面的矩形高</param>
/// <param name="UpColor">正对面的颜色</param>
/// <param name="Graphics">Graphics对象</param>
public void DrawRectangle3D(int x, int y, int width, int length, int height, Color UpColor, Graphics Graphics)
int _x1 = 0;
int _y1 = 0;
SolidBrush Brush;
ChangeXY(out _x1, out _y1, x, y, length);
Pen blackPen = new Pen(Color.Black, 2);
Point point1 = new Point();
Point point2 = new Point();
Point point3 = new Point();
Point point4 = new Point();
Point point5 = new Point();
Point point6 = new Point();
Point point7 = new Point();
Point point8 = new Point();
Brush = new SolidBrush(UpColor);
int[] rgb = new int[3];
rgb[0] = Convert.ToInt32(UpColor.R);
rgb[1] = Convert.ToInt32(UpColor.G);
rgb[2] = Convert.ToInt32(UpColor.B);
float[] hls = new float[3];
Color RightColor;
RgbToHsl(rgb[0], rgb[1], rgb[2], ref hls[0], ref hls[1], ref hls[2]);
hls[1] -= 20f;
HslToRgb(ref rgb[0], ref rgb[1], ref rgb[2], hls[0], hls[1], hls[2]);
RightColor = Color.FromArgb(rgb[0], rgb[1], rgb[2]);
Color TopColor;
RgbToHsl(rgb[0], rgb[1], rgb[2], ref hls[0], ref hls[1], ref hls[2]);
hls[1] -= 20f;
HslToRgb(ref rgb[0], ref rgb[1], ref rgb[2], hls[0], hls[1], hls[2]);
TopColor = Color.FromArgb(rgb[0], rgb[1], rgb[2]);
rgb[0] = Convert.ToInt32(UpColor.R);
rgb[1] = Convert.ToInt32(UpColor.G);
rgb[2] = Convert.ToInt32(UpColor.B);
hls = new float[3];
Brush = new SolidBrush(UpColor);
if (DrawGraphics == null)
AddNumber = 1;
if (AddNumber <= 0) AddNumber = 1;
for (int i = y + height, j = _y1 + height; j >= _y1 && i >= y; i -= AddNumber, j -= AddNumber) //实现着色渐变
{
if (i != y + height)
{
HslToRgb(ref rgb[0], ref rgb[1], ref rgb[2], hls[0], hls[1], hls[2]);
UpColor = Color.FromArgb(rgb[0], rgb[1], rgb[2]);
}
point1 = new Point(x, i);
point2 = new Point(x + width, i);
point5 = new Point(_x1, j);
point6 = new Point(_x1 + width, j);
if (j - AddNumber < _y1)
{
point3 = new Point(_x1, _y1);
point4 = new Point(_x1 + width, _y1);
}
else
{
point3 = new Point(_x1, j - AddNumber);
point4 = new Point(_x1 + width, j - AddNumber);
}
if (i - AddNumber < y)
{
point7 = new Point(x, y);
point8 = new Point(x + width, y);
}
else
{
point7 = new Point(x, i - AddNumber);
point8 = new Point(x + width, i - AddNumber);
}
Point[] curvePointsUp = { point1, point2, point8, point7, };//正对面的点集
Point[] curvePointsRight = { point2, point8, point4, point6, };//右部面的点集
Point[] curvePointsTop = { point7, point8, point4, point3, };//顶部面的点集
Brush = new SolidBrush(UpColor);
if(this.dynamicDraw)
DrawGraphics.FillPolygon(Brush, curvePointsUp);
Graphics.FillPolygon(Brush, curvePointsUp);
Brush = new SolidBrush(RightColor);
if(this.dynamicDraw)
DrawGraphics.FillPolygon(Brush, curvePointsRight);
Graphics.FillPolygon(Brush, curvePointsRight);
Brush = new SolidBrush(TopColor);
if(this.dynamicDraw)
DrawGraphics.FillPolygon(Brush, curvePointsTop);
Graphics.FillPolygon(Brush, curvePointsTop);
RgbToHsl(rgb[0], rgb[1], rgb[2], ref hls[0], ref hls[1], ref hls[2]);
hls[1] -= 100.0f * 1 / (height * 1.0f) * AddNumber;
}
if(this.dynamicDraw)
DrawGraphics.Dispose();
blackPen.Dispose();
Graphics.Dispose();
Brush.Dispose();
}
目前我是这么实现的,画矩形
饼图3d.gif
dynamicDraw,DrawGraphics等一堆变量和函数找不到定义。。
而且,现在实现的是矩形的每个面是用一个颜色填充的吧?
用3张图片代替单纯的颜色应该怎么实现呢?
请教~~
还有你说的图片,我很想知道为什么要用图片,本来画3D就已经够慢了,要是再用上图片就更慢了。
这只是我的理解,再沟通。
protected bool dynamicDraw = true; //是否需要动态画图效果,你可以把它注释掉,这个是用来控制生成图的效果
强!看来要向你好好学习下。。。以后多多关照。。。
QUOTE:
首先,十分感谢您的回答我是想做一个3D效果的菜单,类似于多普达S1的Touch Flow,3D菜单的效果:
05.gif
我现在只是猜测,这个是用Direct 3D实现的,并不知道应该怎么做
如果您有其他的实现方法,请指教,我现在是一头雾水。。
谢谢~~
希望高手出来给你解决下。
旋转.gif
那个插件做的真好,很想知道是怎么实现的。。
要是有源码的话,能有偿给我一份吗?代价好商量。。
是国外一个公司做的。
我以前做过单片机和MTK,对Windows Mobile是一无所知啊,公司里又没有做过Windows Mobile的人,从应用开发到系统定制,全是现学现卖,一个多月了,进展不大,搞得七荤八素,郁闷的不行。。
如果暂时缺乏思路的话,可以找些相关的资料看看,推荐看看webcast,项目的话可以看下Mobile LOB-加速器(Mobile Line of Business )。
我们也可以交流下,如果你愿意的话。
呵呵,类似11楼“旋转.gif”那个应用的效果可以初步实现了,以StretchBlt为核心函数,实现一个梯形打印函数:
CODE:
//梯形方向
这样使用:typedef enum
{
TRIP_DIRECT_H = 0,
TRIP_DIRECT_H_CONVERSE,
TRIP_DIRECT_V,
TRIP_DIRECT_V_CONVERSE,
}ENUM_TRIP_DIRECT;
/************************************************************
* FUNCTION
* StretchRectToTrip
* DESCRIPTION
* 将矩形拉伸为梯形
* PARAMETERS
* hdc: 目标DC(梯形所在DC)
* x1, y1-x4, y4: 矩形的四个顶点(顺序为左上,右上,左下,右下)
* hdcMem: 源DC(矩形所在DC)
* iStartX, iStartY, nWidth, nHeight: 矩形起始位置和宽高
* RETURNS
* void
* AUTHOR:
* Lynn
*************************************************************/
void StretchRectToTrip(HDC hdc, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,
HDC hdcMem, int iStartX, int iStartY, int nWidth, int nHeight)
{
ENUM_TRIP_DIRECT eDirect;
int x, y, w, h, dx, dy; //目标DC
int sx, sy; //源DC
//获取梯形方向
if(y1 == y2 && y3 == y4 && x1 == x3 && x2 == x4)
{
//矩形,直接打印
StretchBlt(hdc, x1, y1, x4 - x1 + 1, y4 - y1 + 1,
hdcMem, iStartX, iStartY, nWidth, nHeight, SRCCOPY);
return;
}
if(y1 == y2 && y3 == y4)
{
if(x1 >= x3 && x2 <= x4)
eDirect = TRIP_DIRECT_H;
else
eDirect = TRIP_DIRECT_H_CONVERSE;
}
else if(x1 == x3 && x2 == x4)
{
if(y1 >= y2 && y3<= y4)
eDirect = TRIP_DIRECT_V;
else
eDirect = TRIP_DIRECT_V_CONVERSE;
}
else
{
//目标图形不是梯形,不能处理
return;
}
//根据不同的方向做图像处理
if(eDirect == TRIP_DIRECT_H || eDirect == TRIP_DIRECT_H_CONVERSE)
{
//梯形高度
h = y3 - y1;
//逐行处理
for(y = 0; y < h; y++)
{
//计算该行的起始X坐标
if(eDirect == TRIP_DIRECT_H)
{
x = x1 - (y * (x1 - x3) / h);
dx = x2 + (y * (x4 - x2) / h);
}
else
{
x = x1 + (y * (x1 - x3) / h);
dx = x3 - (y * (x2 - x4) / h);
}
//计算矩形要Strecth过来的y坐标
sy = y * nHeight / h ;
//处理一行
StretchBlt(hdc, x, y + y1, dx - x + 1, 1, hdcMem, iStartX, sy, nWidth, 1, SRCCOPY);
}
}
else
{
//梯形高度
w = x2 - x1;
//逐行处理
for(x = 0; x < w; x++)
{
//计算列的起始Y坐标
if(eDirect == TRIP_DIRECT_V)
{
y = y1 - (x * (y1 - y2) / w);
dy = y3 + (x * (y4 - y3) / w);
}
else
{
y = y1 + (x * (y2 - y1) / w);
dy = y3 - (x * (y3 - y4) / w);
}
//计算矩形要Strecth过来的X坐标
sx = x * nWidth / w;
//处理一列
StretchBlt(hdc, x + x1, y, 1, dy - y + 1, hdcMem, sx, iStartY, 1, nHeight, SRCCOPY);
}
}
}
CODE:
void DrawScreen(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, HBITMAP hImage)
将屏幕位图传进来,计算好中央矩形/两侧梯形的坐标位置就可以了。测试过了,速度还可以,没有那个软件流畅,但是也不算慢。{
HDC hdc, hdcMem, hdcDoubleBuffer;
HBITMAP bmpDoubleBuffer;
//获取当前屏幕DC并创建设备相关的临时DC
hdc = GetDC(hWnd);
hdcMem = CreateCompatibleDC(hdc);
hdcDoubleBuffer = CreateCompatibleDC(hdc);
bmpDoubleBuffer = CreateCompatibleBitmap(hdc,240,320);
//清空内存缓冲DC
SelectObject(hdcDoubleBuffer, bmpDoubleBuffer);
SelectObject(hdcDoubleBuffer, GetStockObject(BLACK_BRUSH));
Rectangle(hdcDoubleBuffer, 0, 0, 240, 320);
//打印左侧窗体到内存缓冲DC
SelectObject(hdcMem, hImage);
StretchRectToTrip(hdcDoubleBuffer,x1, y1, x2, y2, x3, y3, x4, y4,hdcMem, 0, 0, 240, 320);
//复制到屏幕DC
BitBlt(hdc, 0, 0, 240, 320, hdcDoubleBuffer, 0, 0, SRCCOPY);
DeleteDC(hdc);
DeleteDC(hdcMem);
DeleteDC(hdcDoubleBuffer);
DeleteObject(bmpDoubleBuffer);
}
大概就是这样,应该还有很多优化的余地。比如,备份DC等。也有美化、去掉边缘锯齿的方法,就是在StretchRectToTrip中加入边缘像素点向底背景的RBG色过度的处理,不知道对效率影响大不大,还没试过。