Introduction
The code demonstrates how to use GDI plus create an application with VC6. Many popular MP3 players have desktop lyrics. It's really cool, I like it very much. So I decided tp try to realize it. But I found it's really hard. Here,I should thank all the CodeProject contributors first because I learned much from GDI+ section. After I refreshed the GDI+ functions, I wrote the code. Hope it will help you. This is a gift I send to the members on CodeProject. Happy new year! Download the demo right now and have fun!
Explanation of the Code
Now, let's have a look at the code. How was this demo created. The demo was based on a dialog, not a class. But, I will not talk more about the basic steps of generation of dialog. I suppose you know about the usage of MFC. To look for more, read other articles or MSDN online.
Step 1
We use GDI plus functions, so the first thing is include the header and lib files.
#define UNICODE
#ifndef ULONG_PTR
#define ULONG_PTR unsigned long*
#endif
#include "gdiplus.h" ////Modify your path
using namespace Gdiplus; #pragma comment(lib, "gdiplus.lib")
I add the snippets into the dialog's header. Of course, #include "gdiplus.h"
you can also modify your own path of your computer. Be sure the path is correct, or the VC can't find it.
Step 2
We use the class wizard to add several messages deal functions. WM_CREATE WM_TIMER WM_CONTENTMENU WM_DESTROY WM_LBUTTONDOWN
... for more, download the resources.
We'll use GDI+, so GdiplusStartup()
must be invoked before we use its functions. Before the application exits, we need to invoke another function GdiplusShutdown()
.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
void CGDIAPPDlg::OnDestroy()
{
CDialog::OnDestroy();
GdiplusShutdown(gdiplusToken);
}
Okay! We have finished doing the first job.
Step 3
Initializations for the dialog. We want to invoke the UpdateLayeredWindow()
in the "user32.dll", so we should get the address of the function.
int CGDIAPPDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
hFuncInst = LoadLibrary("User32.DLL");
BOOL bRet=FALSE;
if(hFuncInst)
UpdateLayeredWindow=(MYFUNC)GetProcAddress(hFuncInst, "UpdateLayeredWindow");
else
{
AfxMessageBox("User32.dll ERROR!");
exit(0);
}
m_Blend.BlendOp=0; m_Blend.BlendFlags=0; m_Blend.AlphaFormat=1; m_Blend.SourceConstantAlpha=255;
return 0;
}
Step 4
Okay! Now we begin to think how to draw on desktop. The method is:
- Create a compatible bitmap.
- Draw on the bitmap.
- Draw bitmap on the device content.
- Invoke the UpdateLayeredWindows().
I write a method to do all the jobs like others do (others' snippets). The following is the code. Let's have a look into the details:
BOOL CGDIAPPDlg::UpdateDisplay(int Transparent)
{
HDC hdcTemp=GetDC()->m_hDC;
m_hdcMemory=CreateCompatibleDC(hdcTemp); HBITMAP hBitMap=CreateCompatibleBitmap(hdcTemp,755,350); SelectObject(m_hdcMemory,hBitMap); if(Transparent<0||Transparent>100) Transparent=100;
m_Blend.SourceConstantAlpha=int(Transparent*2.55); HDC hdcScreen=::GetDC (m_hWnd);
RECT rct;
GetWindowRect(&rct);
POINT ptWinPos={rct.left,rct.top};
Graphics graph(m_hdcMemory);
Graphics graphics(m_hdcMemory);
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial Black");
StringFormat strformat;
wchar_t pszbuf[][80]={{L"Hello everyone!"},
{L"Happy New Year!"},
{L"I wish you will lead a happy life!"},
{L"Love you!"},
{L"Thanks all the people on CP!"}
};
GraphicsPath path;
path.AddString(pszbuf[m_kind],wcslen(pszbuf[m_kind]),&fontFamily,
FontStyleRegular,38,Point(10,10),&strformat);
Pen pen(Color(155,215,215,215),3);
graphics.DrawPath(&pen,&path);
LinearGradientBrush linGrBrush(
Point(0,0),Point(0,90),
Color(255,255,255,255),
Color(255,30,120,195));
LinearGradientBrush linGrBrushW(
Point(0,10),Point(0,60),
Color(255,255,255,255),
Color(15,1,1,1));
for(int i=1; i<9; i+=1)
{
Pen pen(Color(62, 0, 2, 2), i);
pen.SetLineJoin(LineJoinRound);
graphics.DrawPath(&pen, &path);
}
SolidBrush brush(Color(25,228,228,228));
Pen pen1(Color(155,223,223,223));
Pen pen2(Color(55,223,223,223));
Image image(L"ly.png");
if(m_bBack)
{
graphics.FillRectangle(&brush,3,5,750,90);
graphics.DrawRectangle(&pen1,2,6,751,91);
graphics.DrawRectangle(&pen2,1,5,753,93);
graphics.DrawImage(&image,600,5);
}
graphics.FillPath(&linGrBrush,&path);
graphics.FillPath(&linGrBrushW,&path);
SIZE sizeWindow={755,350};
POINT ptSrc={0,0};
DWORD dwExStyle=GetWindowLong(m_hWnd,GWL_EXSTYLE); if((dwExStyle&0x80000)!=0x80000)
SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle^0x80000);
BOOL bRet=FALSE;
bRet= UpdateLayeredWindow( m_hWnd,hdcScreen,&ptWinPos,
&sizeWindow,m_hdcMemory,&ptSrc,0,&m_Blend,2);
graph.ReleaseHDC(m_hdcMemory);
::ReleaseDC(m_hWnd,hdcScreen);
hdcScreen=NULL;
::ReleaseDC(m_hWnd,hdcTemp);
hdcTemp=NULL;
DeleteObject(hBitMap);
DeleteDC(m_hdcMemory);
m_hdcMemory=NULL;
return bRet;
}
When the dialog is created, call this method and it does work.
Points of Interest
I learned many new ideas and functions while writing the article. Hope you will also like it! You can use the code in any way, and to create much more stronger applications. Thanks for your support again! Happy new year!