用vc++如何在桌面画一张可响应点击的图片? 就像那种桌面精灵一样. 这几天尝试了N多办法., 把图片画在一个窗口上,然后把窗口透明化.可是那图片也跟着透明化了.. 把窗口透明化,把图片在桌面上跟着窗口的坐标动态显示,但是效果很差用双缓存处理的话画图片质量有很大影响(我用的是半透明的png图片)..有没有只让窗口透明化来响应点击而图片正常显示的办法啊?..跪求啊!
调试欢乐多
楼主说效果不好是不是有闪烁问题,这应该是程序代码问题。
不是闪烁..闪烁用双缓存可以解决..但是问题就出在这. 双缓存需要用CreateCompatibleBitmap在内存创建一个位图..但是这个位图是带信息的..全0的话就是一片黑.全1的话一片白..但是我用的图片是png的..边缘有透明部分..那样的话透明部分的颜色就被内存里的图片给影响了..等到我用TransparentBlt过滤掉底色.把图片传到需要绘制的窗口上时.那png图片已经不透明了. 现在就想解决这个"不透明"的问题有把窗口和图片分别设置透明度的函数吗?? 那样可以直接画在窗口上,把窗口透明,图片不变就解决了..SetLayeredWindowAttribute只能设置一个透明度.那样的话把窗口设成透明,图片也看不到了
当初我是做过的, gdi+应该能花32bit的, 现在,俺全忘了,当初的代码是在磁盘里的,现在电脑没磁盘......
您只能看msdn啦.
但是有一条:这样的窗口只有图片,其他组件都不可见,虽然还起作用,如输入,响应事件等。过会贴上代码
BOOL SetWindowBackgroundImage(HWND hWnd, Image* pImg)
{
int nWidth = pImg->GetWidth();
int nHeight = pImg->GetHeight(); SetWindowPos(hWnd, HWND_TOP, 0, 0, nWidth, nHeight, SWP_NOMOVE); //获取源DC
HDC hdcSource = ::GetDC(hWnd);
//创建内存兼容DC和位图
HDC hdcMemory = ::CreateCompatibleDC(hdcSource);
HBITMAP hbmp = ::CreateCompatibleBitmap(hdcSource, nWidth, nHeight);
HBITMAP hOld = (HBITMAP)::SelectObject(hdcMemory, hbmp);
//采用GDI++画图,保证质量
Graphics Canvas(hdcMemory);
Canvas.SetInterpolationMode(InterpolationModeHighQuality);
Canvas.SetCompositingQuality(CompositingQualityHighQuality);
Canvas.SetSmoothingMode(SmoothingModeAntiAlias);
Canvas.DrawImage(pImg, 0, 0, nWidth, nHeight); //获取屏幕DC
HDC hdcScreen = ::GetDC(NULL); CRect rc;
::GetWindowRect(hWnd, rc);
CPoint ptSource(0, 0); SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255; //如果要改变图像的透明度,可以修改此值0~255。
//0:全透明,255:不透明,由图像本身的Alpha通道决定
bf.AlphaFormat = AC_SRC_ALPHA;
CPoint pt(rc.TopLeft());
CSize size(rc.Size());
BOOL bOK = UpdateLayeredWindow(hWnd, hdcScreen, &pt, &size, hdcMemory, &ptSource, 0, &bf, ULW_ALPHA); ::SelectObject(hdcMemory, hOld);
::DeleteObject(hbmp);
::DeleteDC(hdcMemory);
::ReleaseDC(NULL, hdcScreen);
::ReleaseDC(hWnd, hdcSource); return bOK;
}BOOL SetWindowBackgroundImage(HINSTANCE hInst, HWND hWnd, UINT uID, LPCTSTR lpszType)
{
if (!::IsWindow(hWnd)) return FALSE;
BOOL bSuccessed = FALSE; HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(uID), lpszType); //查找资源
if (hRsrc)
{
DWORD dwSize = SizeofResource(hInst, hRsrc); //获取资源大小
if (dwSize > 0)
{
HGLOBAL hSrc = LoadResource(hInst, hRsrc); //装载资源
if (hSrc)
{
LPVOID lpSrc = LockResource(hSrc); //资源加锁
if (lpSrc)
{
// Allocate global memory on which to create stream
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_NODISCARD|GMEM_ZEROINIT, dwSize);
if (hMem)
{
LPVOID pMem = GlobalLock(hMem);
if (pMem)
{
CopyMemory(pMem, lpSrc, dwSize);
IStream* pstm = NULL;
HRESULT hStatus = CreateStreamOnHGlobal(hMem, FALSE, &pstm);
if (hStatus == S_OK)
{
//从流创建资源图像
Gdiplus::Image* pImg = Gdiplus::Image::FromStream(pstm);
if (pImg)
{
bSuccessed = SetWindowBackgroundImage(hWnd, pImg);
delete pImg;
} pstm->Release();
} GlobalUnlock(hMem);
} GlobalFree(hMem);
}
UnlockResource(hSrc);
}
FreeResource(hSrc);
}
}
}
return bSuccessed;
}
由于使用了GDI++,请自己进行GDI++的初始化和扫尾工作。
那你以后工作也找人代劳么?俺在关键的代码点醒即可,其他的还是靠自己吧,请你尊重俺的劳动。