前段时间对TCPMP程序进行了研究,花了点时间把TCPMP程序的UI修改成了自已想要的样子,现对UI的修改方法简单介绍下:
网上有文章对于TCPMP程序在ARMV4下的编译方法和程序的结构介绍比较详细,但对于inteface方面的修改方法讲得并不多.
修改TCPMP界面基本上有两种方法:
1) 建立自已的工程,把TCPMP下的lib移植到这个工程里,这样界面的修改比较灵活,但是工作量比较大;
2) 直接在TCPMP工程里修改interface,这样工作量相对比较小,但是UI的修改受了定的约束, 没有前种方法灵活.
本人所修改的UI是按照第二种方法来做的.主要是对win_win32.c文件和inteface.c 文件进行修改.
首先,我们来看看win_win32.c文件里的Win_Init()函数,这个函数可以看作是TCPMP UI部分的一个入口,在这个函数里注册了两个窗口类,WinClass和DialogClass.另外还调用了其它控件的初始化函数,下面是这个函数的代码.
view plaincopy to clipboardprint?
void Win_Init()
{
HMODULE Module = Context()->LoadModule;
if (!Module) Module = GetModuleHandle(NULL);
InitCommonControls();
WidcommAudio_Init();
stprintf_s(WinClassName,TSIZEOF(WinClassName),T("%s_Win"),Context()->ProgramName);
memset(&WinClass,0,sizeof(WinClass));
WinClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
WinClass.lpfnWndProc = Proc;
WinClass.cbClsExtra = 0;
WinClass.cbWndExtra = 0;
WinClass.hInstance = Module;
WinClass.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(WIN_ICON));
WinClass.hCursor = WinCursorArrow();
WinClass.hbrBackground =NULL;
WinClass.lpszMenuName = 0;
WinClass.lpszClassName = WinClassName;
RegisterClass(&WinClass);
#if 1
memset(&DialogClass,0,sizeof(DialogClass));
DialogClass.style = CS_HREDRAW | CS_VREDRAW;
DialogClass.lpfnWndProc = DialogProc;
DialogClass.cbClsExtra = 0;
DialogClass.cbWndExtra = 0;
DialogClass.hInstance = Module;
DialogClass.hCursor = WinCursorArrow();
#if defined(TARGET_WINCE)
DialogClass.hbrBackground = GetSysColorBrush(COLOR_STATIC);//
#else
DialogClass.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
#endif
DialogClass.lpszMenuName = 0;
DialogClass.lpszClassName = T("DialogBase");
RegisterClass(&DialogClass);
#endif
memset(&FontCache,0,sizeof(FontCache));
#if defined(TARGET_WINCE)
if (Context()->ProgramId >= 3 && !QueryAdvanced(ADVANCED_OLDSHELL))
{
AygShell = LoadLibrary(T("aygshell.dll"));
*(FARPROC*)&FuncSHCreateMenuBar = GetProcAddress(AygShell,T("SHCreateMenuBar"));
*(FARPROC*)&FuncSHInitDialog = GetProcAddress(AygShell,T("SHInitDialog"));
*(FARPROC*)&FuncSHFullScreen = GetProcAddress(AygShell,T("SHFullScreen"));
*(FARPROC*)&FuncSHHandleWMActivate = GetProcAddress(AygShell,MAKEINTRESOURCE(84));
*(FARPROC*)&FuncSHHandleWMSettingChange = GetProcAddress(AygShell,MAKEINTRESOURCE(83));
*(FARPROC*)&FuncSHSendBackToFocusWindow = GetProcAddress(AygShell,MAKEINTRESOURCE(97));
}
CoreDLL = LoadLibrary(T("coredll.dll"));
*(FARPROC*)&FuncUnregisterFunc1 = GetProcAddress(CoreDLL,T("UnregisterFunc1"));
*(FARPROC*)&FuncAllKeys = GetProcAddress(CoreDLL,T("AllKeys"));
*(FARPROC*)&FuncSipShowIM = GetProcAddress(CoreDLL,T("SipShowIM"));
*(FARPROC*)&FuncSipGetInfo = GetProcAddress(CoreDLL,T("SipGetInfo"));
#endif
NodeRegisterClass(&Win);
QueryKey_Init();
OpenFile_Init();
Interface_Init();
PlaylistWin_Init();
PlaylistNewWin_Init();
}
void Win_Init()
{
HMODULE Module = Context()->LoadModule;
if (!Module) Module = GetModuleHandle(NULL);
InitCommonControls();
WidcommAudio_Init();
stprintf_s(WinClassName,TSIZEOF(WinClassName),T("%s_Win"),Context()->ProgramName);
memset(&WinClass,0,sizeof(WinClass));
WinClass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
WinClass.lpfnWndProc = Proc;
WinClass.cbClsExtra = 0;
WinClass.cbWndExtra = 0;
WinClass.hInstance = Module;
WinClass.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE(WIN_ICON));
WinClass.hCursor = WinCursorArrow();
WinClass.hbrBackground =NULL;
WinClass.lpszMenuName = 0;
WinClass.lpszClassName = WinClassName;
RegisterClass(&WinClass);
#if 1
memset(&DialogClass,0,sizeof(DialogClass));
DialogClass.style = CS_HREDRAW | CS_VREDRAW;
DialogClass.lpfnWndProc = DialogProc;
DialogClass.cbClsExtra = 0;
DialogClass.cbWndExtra = 0;
DialogClass.hInstance = Module;
DialogClass.hCursor = WinCursorArrow();
#if defined(TARGET_WINCE)
DialogClass.hbrBackground = GetSysColorBrush(COLOR_STATIC);//
#else
DialogClass.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
#endif
DialogClass.lpszMenuName = 0;
DialogClass.lpszClassName = T("DialogBase");
RegisterClass(&DialogClass);
#endif
memset(&FontCache,0,sizeof(FontCache));
#if defined(TARGET_WINCE)
if (Context()->ProgramId >= 3 && !QueryAdvanced(ADVANCED_OLDSHELL))
{
AygShell = LoadLibrary(T("aygshell.dll"));
*(FARPROC*)&FuncSHCreateMenuBar = GetProcAddress(AygShell,T("SHCreateMenuBar"));
*(FARPROC*)&FuncSHInitDialog = GetProcAddress(AygShell,T("SHInitDialog"));
*(FARPROC*)&FuncSHFullScreen = GetProcAddress(AygShell,T("SHFullScreen"));
*(FARPROC*)&FuncSHHandleWMActivate = GetProcAddress(AygShell,MAKEINTRESOURCE(84));
*(FARPROC*)&FuncSHHandleWMSettingChange = GetProcAddress(AygShell,MAKEINTRESOURCE(83));
*(FARPROC*)&FuncSHSendBackToFocusWindow = GetProcAddress(AygShell,MAKEINTRESOURCE(97));
}
CoreDLL = LoadLibrary(T("coredll.dll"));
*(FARPROC*)&FuncUnregisterFunc1 = GetProcAddress(CoreDLL,T("UnregisterFunc1"));
*(FARPROC*)&FuncAllKeys = GetProcAddress(CoreDLL,T("AllKeys"));
*(FARPROC*)&FuncSipShowIM = GetProcAddress(CoreDLL,T("SipShowIM"));
*(FARPROC*)&FuncSipGetInfo = GetProcAddress(CoreDLL,T("SipGetInfo"));
#endif
NodeRegisterClass(&Win);
QueryKey_Init();
OpenFile_Init();
Interface_Init();
PlaylistWin_Init();
PlaylistNewWin_Init();
}
在此函数中我们需要注意 WinClass.lpfnWndProc= Proc; Proc是消息处理函数名.实际上所有的消息处理都是在static LRESULT CALLBACK Proc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)函数里完成的.
下面对此函数中比较重点的消息作下说明:
WM_CREATE消息里主要是建立播放的窗口;
WM_PAINT消息里可以贴上UI的背景图片,这样使UI看上去比较美观.贴图部分程序如下:
view plaincopy to clipboardprint?
case WM_PAINT:
{
hdc = BeginPaint(Wnd,&Paint);
MainBkGnd = LoadBitmap(p->Module,MAKEINTRESOURCE(IDB_MAIN_BKG));
MemDC = CreateCompatibleDC(hdc);
bmpOld = (HBITMAP)SelectObject(MemDC,MainBkGnd);
BitBlt(hdc,0,0,LCD_XSIZE,LCD_YSIZE,MemDC,0,0,SRCCOPY);
SelectObject(MemDC,bmpOld);
DeleteObject(bmpOld);
DeleteDC(MemDC);
EndPaint(Wnd,&Paint);
}
break;
case WM_PAINT:
{
hdc = BeginPaint(Wnd,&Paint);
MainBkGnd = LoadBitmap(p->Module,MAKEINTRESOURCE(IDB_MAIN_BKG));
MemDC = CreateCompatibleDC(hdc);
bmpOld = (HBITMAP)SelectObject(MemDC,MainBkGnd);
BitBlt(hdc,0,0,LCD_XSIZE,LCD_YSIZE,MemDC,0,0,SRCCOPY);
SelectObject(MemDC,bmpOld);
DeleteObject(bmpOld);
DeleteDC(MemDC);
EndPaint(Wnd,&Paint);
}
break;
WM_COMMAND消息是所有菜单 ,按钮等点击后处理的入口点,具体的实现在interface.c里的static int Command(intface* p,int Cmd)函数里来做处理。如播放,暂停,前一首,下一首等.还有其它的一些消息处理在此不做介绍了.
Interface.c的程序结构和win_win32.c 基本差不多,其中最主要的也是static bool_t Proc(intface* p, int Msg, uint32_t wParam, uint32_t lParam, int* Result)函数对消息的处理.在此函数的WM_CREATE消息里可以建立起各种控件的消息处理.然后分别在各控件的消息处理函数里通过上面贴 bitmap图片的方式来改变控件的外观.
其实对于TCPMP程序UI部分的修改,最主要的还是要读懂源代码.在读懂源代码的基础上再结合Win32程序的结构来修改界面还是比较容易的.
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xxxluozhen/archive/2010/02/24/5321694.aspx
Interface插件功能模块包含在interface文件夹下,其中的interface.c实现图形界面的大部分功能,还有小部分功能在 win_win32.c文件中实现.程序运行过程基本有下面几个步骤:
1.多媒体播放器运行程序为player.exe ,工程中main.c文件的WinMain函数为程序开始的第一步.
2.common工程是核心模块,是一个开放的集数据输入、转换、音/视频解码、信号输出等功能为一体的完整的多媒体播放框架。WinMain后调用 common.dll中的Contxt_Init函数,完成各个功能模块ID的注册工作.除Interface功能外,其他功能模块的注册基本在 Contxt_Init中完成.
3.系统调用interface.dll中DLLRegister函数对INTREFACE_ID对象进行注册,对象注册完成创建和内存分配等功能.下图为程序WinMain开始至DLLRegister注册过程的堆栈状态.
Interface插件功能模块包含在interface文件夹下,其中的interface.c实现图形界面的大部分功能,还有小部分功能在 win_win32.c文件中实现.程序运行过程基本有下面几个步骤:
1.多媒体播放器运行程序为player.exe ,工程中main.c文件的WinMain函数为程序开始的第一步.
2.common工程是核心模块,是一个开放的集数据输入、转换、音/视频解码、信号输出等功能为一体的完整的多媒体播放框架。WinMain后调用 common.dll中的Contxt_Init函数,完成各个功能模块ID的注册工作.除Interface功能外,其他功能模块的注册基本在 Contxt_Init中完成.
3.系统调用interface.dll中DLLRegister函数对INTREFACE_ID对象进行注册,对象注册完成创建和内存分配等功能.下图为程序WinMain开始至DLLRegister注册过程的堆栈状态.
4.注册后interface.c中Create函数对INTREFACE_ID对象intface* p进行初始化,完成界面状态的最初设置.
5.主窗口创建与弹出,win_win32.c文件中WinPopupClass函数调用Popup函数,Popup实现窗口创建功能.
6.Popup函数中调用HandleMessage(p,&Msg),该函数为消息响应函数,Popup完成主窗口创建的后给 HandleMessage函数发送WM_CREATE消息.
7.WM_CREATE消息响应分两部分,win_win32.c中的CALLBACK Proc首先响应,完成窗口工具栏的创建,然后interface.c中的bool_t Proc函数再响应完成工具栏中系统菜单,进度条,播放控件和声音控制的创建.
改写TCPMP的界面非常简单。你可以看到TCPMP目录下面有一个Sample的目录,其中的sample_win32.c实现了对Player的调用,Player就是指播放器。它是一个没有界面的程序,但是它能很正常的播放视频,操作完全是Player指针。你可以通过这个Player指针来操作上一曲,下一曲,暂停,播放,停止等操作。界面你可以完全自己配。Player和你的界面交互也可以通过设置Notify来实现。这么说可能还有点迷糊。下面举个例子看怎么调用Player指针
Player->Set(Player, PLAYER_LIST_URL+0, URL, sizeof(URL)); //这个就是设置播放的文件
Player->Set(Player, PLAYER_FULLSCREEN, &Bool, sizeof(Bool)); // 这个就是设置全屏播放
TCPMP是一个模块化很强的程序,node是每个模块的联系纽带。每个node都会有一些设置属性通过函数Set和Get来进行属性的操作。 Player就是一个node,它当然也有很多属性,出来上面的PLAYER_LIST_URL,PLAYER_FULLSCREEN, 在common目录下的Player.h文件中,你可以看到它定义了一系列的PLAYER_×××,在仔细看看它的注释,这些就是Player的所有操作。你只要知道了Player指针,你可以做播放器里的任何它这边已经定义好的操作。