本文通过重载WM_NOTIFY消息,实现ListView外观的自定义.
实现结果为奇偶数分别采用不同的背景颜色.同时最后一列加入了一个时钟图标.
该代码为本人的GUI系统(MiniWin)在数字电视机顶盒中的部分实现代码
需要学习WIN32-API开发的人可以参考,
其中IDC_EPGSCHEDULE为Listview控件的ID
以下为MiniWin界面效果图以及相关代码.其中包含了ListBox自绘模式的实现,ToolBar的应用等
//
epgWindow.c: implementation of the epgWindow class.
//
/**/ //
#include " dvbutils.h "
#include < stdio.h >
#include < string .h >
#include " dvbepg.h "
#include " prvideo.h "
#define WM_EVENT_UPDATE WM_LAST+0x1000
#define IDT_EPGTIMER 100
#define IDC_TITLE 101
#define IDC_DATETIME 102
#define IDC_SVCGROUPS 103
#define IDC_GRPSERVICE 104
#define IDC_WEEK 105
#define IDC_EPGSCHEDULE 107
#define IDC_VIDEO 108
static HBITMAP hbmpClock;
extern int GetAllService(HWND hwnd,FAVGROUP * fav);
static int UpdateScheduleInfo(HWND hch,SECTIONDB * db, int week)
... {
int i,evtCount=0;
DWORD t1=GetTickCount();
LockWindowUpdate(hch);
SendMessage(hch,LVM_DELETEALLITEMS,0,0);
if(db!=NULL)...{
SECTIONDATA*sd;
SYSTEMTIME curTime;
FILETIME CurFt;
GetLocalTime(&curTime);
SystemTimeToFileTime(&curTime,&CurFt);
sd=db->sections;
if(sd&&sd->Data)
TRACE("Update EITS %d.%d.%d=%dSections ",GetEitNetID(sd->Data),
GetEitStreamID(sd->Data),GetEitServiceID(sd->Data),db->Count);
while(sd)...{
int i,ec=GetEitEventCount(sd->Data);
for(i=0;i<ec;i++)...{
DVBEvent evt;
int idx;
UINT duration;
char tstr[256],name[256],txt[256];
FILETIME ft;
SYSTEMTIME evtLocalTime;
LVITEM lv;
GetEitEvent(sd->Data,&evt,i);
MJDToLocalTime(&evtLocalTime,evt.mjdDate,evt.utcTime);
//MJDToSystemTime(&est,evt.mjdDate,evt.utcTime);
if(evtLocalTime.wDayOfWeek!=week)continue;
sprintf(tstr,"%02d:%02d",evtLocalTime.wHour,evtLocalTime.wMinute);
duration=UTC2Seconds(evt.duration);
SystemTimeToFileTime(&evtLocalTime,&ft);
ZeroMemory(&lv,sizeof(lv));
lv.pszText=tstr;
lv.mask=LVIF_TEXT|LVIF_PARAM;
lv.iItem=evtCount+i;
lv.lParam=ft.dwLowDateTime;
idx=ListView_InsertItem(hch,&lv);
lv.lParam=0;
if( (ft.dwLowDateTime<CurFt.dwLowDateTime) &&
( ft.dwLowDateTime+duration>CurFt.dwLowDateTime) )...{
ListView_SetItemState(hch,idx,LVIS_FOCUSED | LVIS_SELECTED,LVIS_FOCUSED | LVIS_SELECTED );
ListView_EnsureVisible(hch,idx,0);
//Make sure Current Event is selected and Visible
}
sprintf(tstr,"%02X:%02X",evt.duration>>16,(evt.duration>>8)&0xFF);
ListView_SetItemText(hch,idx,1,tstr);
GetShortEventName(&evt,name,txt,NULL);
ListView_SetItemText(hch,idx,2,name);
ListView_SetItemText(hch,idx,3," ");
ListView_SetItemText(hch,idx,4,txt);
}
evtCount+=ec;
sd=sd->next;
}
}
LockWindowUpdate(NULL);
TRACE("UpdateScheduleInfo used %d ms ",GetTickCount()-t1);
return evtCount;
}
static INT DoServiceChange(HWND hwnd) ... {
HWND hgrpsvc=GetDlgItem(hwnd,IDC_GRPSERVICE);
INT rc,idx=SendMessage(hgrpsvc,LB_GETCURSEL,0,0);
SERVICELOCATOR *svr=(SERVICELOCATOR*)SendMessage(hgrpsvc,LB_GETITEMDATA,idx,0);
HWND hSch,hweek=GetDlgItem(hwnd,IDC_WEEK);
TCITEM tci;
SECTIONDB *sdb=NULL;
tci.mask=TCIF_PARAM;
hSch=GetDlgItem(hwnd,IDC_EPGSCHEDULE);
TabCtrl_GetItem(hweek,TabCtrl_GetCurSel(hweek),&tci);
if( (svr!=NULL) && ((UINT)svr!=LB_ERR))...{
PlayByService(svr);
sdb=LockScheduleDB(svr);//PlayByService会自动发送接收EITSchedule的请求
if(sdb==NULL||sdb->sections==NULL)...{
TRACE("EPG::Request(%d.%d.%d) ",svr->netId,svr->tsId,svr->serviceId);
//RequestEPG(svr,REQUEST_EITSCH);
rc=0;
}else...{
rc=UpdateScheduleInfo(hSch,sdb,tci.lParam);
UnlockScheduleDB(svr);//PlayByService会自动发送接收EITSchedule的请求
}
}
return rc;
}
static LRESULT WINAPI EpgWndProc(HWND hwnd,UINT msgID,WPARAM wParam,LPARAM lParam)
... {
switch(msgID)
...{
case WM_TIMER:
...{
char sdate[128],stime[64];
SYSTEMTIME tnow;
GetLocalTime(&tnow);
GetDateFormat(LOCALE_NEUTRAL,0,&tnow,0,sdate,64);
GetTimeFormat(LOCALE_NEUTRAL,TIME_NOSECONDS|TIME_FORCE24HOURFORMAT,&tnow," hh:mm tt",stime,64);
strcat(sdate,stime);
SetDlgItemText(hwnd,IDC_DATETIME,sdate);
}
break;
case WM_COMMAND:
...{
switch(wParam)
...{
case MAKELONG(IDC_SVCGROUPS,OPN_SELCHANGE)://分组改变事件处理
...{
INT idx=SendMessage((HWND)lParam,OPT_GETCURSEL,0,0);
FAVGROUP*fav=(FAVGROUP*)SendMessage((HWND)lParam,OPT_GETITEMDATA,idx,0);
HWND hs=GetDlgItem(hwnd,IDC_GRPSERVICE);
GetAllService(hs,(FAVGROUP*)fav);
}
break;
case MAKELONG(IDC_WEEK,OPN_SELCHANGE)://分组改变事件处理
TRACE("WEEK CHANGE ");
//pass throught
case MAKELONG(IDC_GRPSERVICE,LBN_SELCHANGE)://Service切换事件处理
DoServiceChange(hwnd);
break;
default:
break;
}
}break;
case WM_DRAWITEM:
...{
DRAWITEMSTRUCT *ds=(DRAWITEMSTRUCT*)lParam;
HDC hdc=(HDC)ds->hDC;
RECT rc=ds->rcItem;
char text[128];
HBRUSH hbBorder;
HDC hmdc=CreateCompatibleDC((HDC)hdc);
if(ds->CtlType==ODT_LISTBOX)
...{
HBRUSH hb;
HBRUSH hbBorder=CreateSolidBrush(RGB(214,247,255));
HRGN hrgn=CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom,0,0);
if(ds->itemState&ODS_SELECTED)...{
if(ds->itemState&ODS_FOCUS)
hb=CreateSolidBrush(RGB(207,99,22));
else
hb=CreateSolidBrush(RGB(255,255,181));
}else
hb=CreateSolidBrush(RGB(24,141,185));
FillRgn(hdc,hrgn,hb);
FrameRgn(hdc,hrgn,hbBorder,0,2);
SendMessage(ds->hwndItem,LB_GETTEXT,ds->itemID,(LPARAM)text);
SetBkMode(hdc,TRANSPARENT);
SetTextColor(hdc,RGB(0,0,0));
DrawText(hdc,text,sizeof(text),&rc,DT_VCENTER|DT_SINGLELINE|DT_LEFT);
SendMessage(ds->hwndItem,LB_GETITEMDATA,ds->itemID,0);
DeleteObject((HGDIOBJ)hb);
DeleteObject((HGDIOBJ)hrgn);
DeleteObject((HGDIOBJ)hbBorder);
}
DeleteDC(hmdc);
}
return 0;
case WM_ERASEBKGND:
...{
HDC hmdc=CreateCompatibleDC((HDC)wParam);
HBRUSH hbBorder;
//画菜单背景
hbBorder=CreateSolidBrush(RGB(61,185,197));
FillRect((HDC)wParam,NULL,hbBorder);
DeleteObject((HGDIOBJ)hbBorder);
...{
RECT rc;
HBITMAP hbmpTitle;
HBRUSH hbrush;
BITMAP bmp;
hbmpTitle=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_WINTITLE));
hbrush=CreatePatternBrush(hbmpTitle);
GetObject((HGDIOBJ)hbmpTitle,sizeof(BITMAP),&bmp);
GetClientRect(hwnd,&rc);rc.bottom=rc.top+bmp.bmHeight;
FillRect((HDC)wParam,&rc,hbrush);
DeleteObject((HGDIOBJ)hbrush);
DeleteObject((HGDIOBJ)hbmpTitle);
hbmpTitle=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_WINHELP));
hbrush=CreatePatternBrush(hbmpTitle);
GetObject((HGDIOBJ)hbmpTitle,sizeof(BITMAP),&bmp);
GetClientRect(hwnd,&rc);rc.top=rc.bottom-bmp.bmHeight;
FillRect((HDC)wParam,&rc,hbrush);
DeleteObject((HGDIOBJ)hbrush);
DeleteObject((HGDIOBJ)hbmpTitle);
}
DeleteDC(hmdc);
}
return 0;
case WM_NOTIFY:
...{
NMHDR *nmhdr = (PVOID)lParam;
if(nmhdr->code==TCN_SELCHANGE)...{
DoServiceChange(hwnd);
}
if(nmhdr->idFrom ==IDC_EPGSCHEDULE)...{
if(nmhdr->code == NM_CUSTOMDRAW) ...{
NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
SYSTEMTIME stnow;
FILETIME ft;
switch(nmlvcd->nmcd.dwDrawStage) ...{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
GetLocalTime(&stnow);
SystemTimeToFileTime(&stnow,&ft);
if(nmlvcd->nmcd.lItemlParam<ft.dwLowDateTime)...{
if(nmlvcd->nmcd.uItemState!=0)
nmlvcd->clrTextBk =CLR_DEFAULT;
else...{
nmlvcd->clrTextBk =RGB(200,200,200);
}
return CDRF_DODEFAULT;
}
return CDRF_NOTIFYSUBITEMDRAW;
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
if(nmlvcd->nmcd.dwItemSpec%2)...{
nmlvcd->clrTextBk =CLR_DEFAULT;
}else
nmlvcd->clrTextBk =RGB(200,200,250);
return CDRF_NOTIFYPOSTPAINT;
case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
if(nmlvcd->iSubItem==3)...{
BITMAP bmp;
RECT rc=nmlvcd->nmcd.rc;
HBITMAP hobmp,hbm=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_CLOCK));
HDC hmdc=CreateCompatibleDC(nmlvcd->nmcd.hdc);
hobmp=(HBITMAP)SelectObject(hmdc,(HGDIOBJ)hbm);
GetObject((HGDIOBJ)hbm,sizeof(BITMAP),&bmp);
BitBlt(nmlvcd->nmcd.hdc,rc.left,
rc.top+(RECTH(&rc)-bmp.bmHeight)/2,24,24,hmdc,0,0,SRCCOPY);
SelectObject(hmdc,(HGDIOBJ)hobmp);
DeleteObject((HGDIOBJ)hbm);
DeleteDC(hmdc);
return CDRF_SKIPDEFAULT;
}
return CDRF_DODEFAULT;
}
return CDRF_DODEFAULT;
}else if(nmhdr->code==LVN_ITEMCHANGED)...{
LPNMLISTVIEW lv=(LPNMLISTVIEW)lParam;
SetWindowLong(lv->hdr.hwndFrom,GWL_USERDATA,lv->iItem);
}else if(nmhdr->code==LVN_KEYDOWN)...{
LPNMLVKEYDOWN lk=(LPNMLVKEYDOWN)lParam;
CHAR desc[256];
LVITEM itm;
itm.mask=LVIF_TEXT;
itm.iItem=GetWindowLong(lk->hdr.hwndFrom,GWL_USERDATA);
itm.iSubItem=3;
itm.pszText=desc;
itm.cchTextMax=256;
ListView_GetItem(lk->hdr.hwndFrom,&itm);
if(lk->wVKey==VK_RETURN)
MessageBox(hwnd,desc,"节目简介",0);
}
}
}break;
case WM_DESTROY:
DeleteObject((HGDIOBJ)hbmpClock);
return DefWindowProc(hwnd,msgID,wParam,lParam);
case WM_CLOSE:
PrVideoSetOutputWindow(0,0,720,576);
//RegisterEPGNotify(NULL);
DefWindowProc(hwnd,msgID,wParam,lParam);
break;
case WM_ACTIVATE:
if(wParam)...{
RECT rc;
GetWindowRect(GetDlgItem(hwnd,IDC_VIDEO),(LPRECT)&rc);
PrVideoSetOutputWindow(rc.left,rc.top,RECTW(&rc),RECTH(&rc));
}
return DefWindowProc(hwnd,msgID,wParam,lParam);
default:
return DefWindowProc(hwnd,msgID,wParam,lParam);
}
return 0;
}
static void CreateListView(HWND hwnd, int count)
... {
int i;
LVCOLUMN lc;
char *titles[]=...{"开始时间","片长","片名","预定","节目介绍"};
int width[]=...{120,160,220,60,100};
//WS_EX_DLGMODALFRAME和LVS_EX_GRIDLINES定义存在冲突,会导致NC区域边框出现问题
HWND hv=CreateWindowEx(LVS_EX_FULLROWSELECT/**//*|LVS_EX_GRIDLINES*/,"ListView",NULL,
WS_TABSTOP|WS_CHILD|WS_VSCROLL|WS_VISIBLE|LVS_SHOWSELALWAYS//|LVS_SINGLESEL
|LVS_REPORT|LVS_NOCOLUMNHEADER,//|LVS_OWNERDRAWFIXED|,
36,286,582,175,hwnd,(HMENU)IDC_EPGSCHEDULE,NULL,NULL);
for(i=0;i<sizeof(titles)/sizeof(char*);i++)
...{
lc.pszText=titles[i];
lc.cx=width[i];
lc.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_FMT;
lc.fmt=i==0?LVCFMT_RIGHT:LVCFMT_LEFT;
SendMessage(hv,LVM_INSERTCOLUMN,i,(LPARAM)&lc);
}
}
HWND CreateEpgWnd(UINT grpId)
... {
int i;
HWND ch,DispWin;
SYSTEMTIME tnow;
HWND epgWnd;
HWND hg;
HWND htab;
epgWnd = CreateMainWindow(NULL,WS_TABSTOP|WS_OVERLAPPED,40,30,650,520,EpgWndProc);
GetLocalTime(&tnow);
CreateWindow("Static",NULL,WS_VISIBLE|WS_CHILD|SS_LEFT,//|SS_OWNERDRAW,
350,13,290,25,epgWnd,(HMENU)IDC_DATETIME,NULL,NULL);
//标题
CreateWindow("Static","节 目 指 南",WS_VISIBLE|WS_CHILD,//|SS_OWNERDRAW,
40,13,200,24,epgWnd,(HMENU)IDC_TITLE,NULL,NULL);
hg=CreateWindow("Select",NULL,WS_VISIBLE|WS_CHILD|WS_BORDER|
OPS_SHOWARROWALWAYS|OPS_NOLABEL|WS_DISABLED,//(grpId==0xFFFFFFFF?0:WS_DISABLED),
35,60,325,27,epgWnd,(HMENU)IDC_SVCGROUPS,NULL,NULL);
if (NULL != hg)
...{
FAVGROUP*fav;
CreateDefaultGroup(FALSE);
UpdateAllGroup();
fav=GetFirstFavGroup();//添加分组数据
for(i=0;fav;fav=fav->next,i++)...{
INT idx;
idx=SendMessage(hg,OPT_ADDSTRING,i,(LPARAM)fav->name);
SendMessage(hg,OPT_SETITEMDATA,idx,fav);
if(grpId==0xFFFF)
SendMessage(hg,OPT_SETCURSEL,0,(LPARAM)0);
else if(grpId==fav->FavId)
SendMessage(hg,OPT_SETCURSEL,idx,0);
}
}
ch=CreateWindow("Listbox",NULL,WS_TABSTOP|WS_VSCROLL|WS_VISIBLE|WS_CHILD|
LBS_OWNERDRAWFIXED|LBS_HASSTRINGS|LBS_NOTIFY|LBS_WRAP,
35,96,325,150,epgWnd,(HMENU)IDC_GRPSERVICE,NULL,NULL);
if (NULL != ch)
...{
FAVGROUP*fav;
fav=FindFavGroupByID(grpId==0xFFFF?GROUP_ALL:grpId);
//添加业务数据
GetAllService(ch,fav);
SendMessage(ch,LB_SETITEMHEIGHT,0,30);
SendMessage(ch,LB_SETCURSEL,0,0);
}
//电视窗口
DispWin=CreateWindow("Static",NULL,WS_VISIBLE|WS_CHILD|SS_OWNERDRAW,
370,60,250,178,epgWnd,(HMENU)IDC_VIDEO,NULL,NULL);
//将电视窗口变为圆角矩形
...{
RECT rc;
HRGN rgn;
GetWindowRect(DispWin,(LPRECT)&rc);
rgn=CreateRoundRectRgn(0,0,RECTW(&rc),RECTH(&rc),10,10);
SetWindowRgn(DispWin,rgn,FALSE);
DeleteObject((HGDIOBJ)rgn);
}
htab=CreateWindow("tabcontrol",NULL,WS_VISIBLE|WS_TABSTOP|WS_CHILD|TCS_BUTTONS|TCS_HOTTRACK|TCS_FOCUSONBUTTONDOWN,//|TCS_OWNERDRAWFIXED,
36,258,582,27,epgWnd,(HMENU)IDC_WEEK,NULL,NULL);
if(NULL != htab)
...{
TCITEM itm;
int i;
GetLocalTime(&tnow);
itm.mask=TCIF_TEXT|TCIF_PARAM;
for (i=0; i<7; i++)...{
CHAR wname[32];
GetLocaleInfo(LOCALE_NEUTRAL,
tnow.wDayOfWeek==0?LOCALE_SDAYNAME7:(LOCALE_SDAYNAME1+tnow.wDayOfWeek-1),wname,32);
itm.lParam=tnow.wDayOfWeek;
tnow.wDayOfWeek=(tnow.wDayOfWeek+1)%7;
itm.pszText = wname;
TabCtrl_InsertItem(htab,i,&itm);
}
SendMessage(htab,TCM_SETCURSEL,0,0);
}
CreateListView(epgWnd,100);
...{
TBBUTTON toolbarBtns[] = ...{
...{0, 0, 0, BTNS_SEP, ...{0, 0}, 0, 0},
...{0, 123, TBSTATE_ENABLED,BTNS_BUTTON, ...{0, 0}, 0, "选择"},
...{1, 122, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, 0},
...{2, 133, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, "Test"},
...{3, 144, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, 0},
...{4, 145, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, 0},
...{5, 156, TBSTATE_ENABLED, BTNS_BUTTON|BTNS_DROPDOWN, ...{0, 0}, 0, 0},
};
HWND htoolbar=CreateToolbarEx(epgWnd, WS_CHILD|WS_VISIBLE|
TBSTYLE_LIST|TBSTYLE_TRANSPARENT|TBSTYLE_FLAT|CCS_BOTTOM,
1234, 2, hInstDVBRes, IDB_COLORKEYS, toolbarBtns,
sizeof(toolbarBtns)/sizeof(TBBUTTON), 36, 18, 36, 18, sizeof(TBBUTTON));
SendMessage(htoolbar,TB_SETEXTENDEDSTYLE,0, TBSTYLE_EX_DRAWDDARROWS);
}
ShowWindow(epgWnd,SW_SHOW);
//SetFocus(GetDlgItem(epgWnd,IDC_GRPSERVICE));
SetTimer(epgWnd,IDT_EPGTIMER,1000,NULL);
return epgWnd;
}
//
/**/ //
#include " dvbutils.h "
#include < stdio.h >
#include < string .h >
#include " dvbepg.h "
#include " prvideo.h "
#define WM_EVENT_UPDATE WM_LAST+0x1000
#define IDT_EPGTIMER 100
#define IDC_TITLE 101
#define IDC_DATETIME 102
#define IDC_SVCGROUPS 103
#define IDC_GRPSERVICE 104
#define IDC_WEEK 105
#define IDC_EPGSCHEDULE 107
#define IDC_VIDEO 108
static HBITMAP hbmpClock;
extern int GetAllService(HWND hwnd,FAVGROUP * fav);
static int UpdateScheduleInfo(HWND hch,SECTIONDB * db, int week)
... {
int i,evtCount=0;
DWORD t1=GetTickCount();
LockWindowUpdate(hch);
SendMessage(hch,LVM_DELETEALLITEMS,0,0);
if(db!=NULL)...{
SECTIONDATA*sd;
SYSTEMTIME curTime;
FILETIME CurFt;
GetLocalTime(&curTime);
SystemTimeToFileTime(&curTime,&CurFt);
sd=db->sections;
if(sd&&sd->Data)
TRACE("Update EITS %d.%d.%d=%dSections ",GetEitNetID(sd->Data),
GetEitStreamID(sd->Data),GetEitServiceID(sd->Data),db->Count);
while(sd)...{
int i,ec=GetEitEventCount(sd->Data);
for(i=0;i<ec;i++)...{
DVBEvent evt;
int idx;
UINT duration;
char tstr[256],name[256],txt[256];
FILETIME ft;
SYSTEMTIME evtLocalTime;
LVITEM lv;
GetEitEvent(sd->Data,&evt,i);
MJDToLocalTime(&evtLocalTime,evt.mjdDate,evt.utcTime);
//MJDToSystemTime(&est,evt.mjdDate,evt.utcTime);
if(evtLocalTime.wDayOfWeek!=week)continue;
sprintf(tstr,"%02d:%02d",evtLocalTime.wHour,evtLocalTime.wMinute);
duration=UTC2Seconds(evt.duration);
SystemTimeToFileTime(&evtLocalTime,&ft);
ZeroMemory(&lv,sizeof(lv));
lv.pszText=tstr;
lv.mask=LVIF_TEXT|LVIF_PARAM;
lv.iItem=evtCount+i;
lv.lParam=ft.dwLowDateTime;
idx=ListView_InsertItem(hch,&lv);
lv.lParam=0;
if( (ft.dwLowDateTime<CurFt.dwLowDateTime) &&
( ft.dwLowDateTime+duration>CurFt.dwLowDateTime) )...{
ListView_SetItemState(hch,idx,LVIS_FOCUSED | LVIS_SELECTED,LVIS_FOCUSED | LVIS_SELECTED );
ListView_EnsureVisible(hch,idx,0);
//Make sure Current Event is selected and Visible
}
sprintf(tstr,"%02X:%02X",evt.duration>>16,(evt.duration>>8)&0xFF);
ListView_SetItemText(hch,idx,1,tstr);
GetShortEventName(&evt,name,txt,NULL);
ListView_SetItemText(hch,idx,2,name);
ListView_SetItemText(hch,idx,3," ");
ListView_SetItemText(hch,idx,4,txt);
}
evtCount+=ec;
sd=sd->next;
}
}
LockWindowUpdate(NULL);
TRACE("UpdateScheduleInfo used %d ms ",GetTickCount()-t1);
return evtCount;
}
static INT DoServiceChange(HWND hwnd) ... {
HWND hgrpsvc=GetDlgItem(hwnd,IDC_GRPSERVICE);
INT rc,idx=SendMessage(hgrpsvc,LB_GETCURSEL,0,0);
SERVICELOCATOR *svr=(SERVICELOCATOR*)SendMessage(hgrpsvc,LB_GETITEMDATA,idx,0);
HWND hSch,hweek=GetDlgItem(hwnd,IDC_WEEK);
TCITEM tci;
SECTIONDB *sdb=NULL;
tci.mask=TCIF_PARAM;
hSch=GetDlgItem(hwnd,IDC_EPGSCHEDULE);
TabCtrl_GetItem(hweek,TabCtrl_GetCurSel(hweek),&tci);
if( (svr!=NULL) && ((UINT)svr!=LB_ERR))...{
PlayByService(svr);
sdb=LockScheduleDB(svr);//PlayByService会自动发送接收EITSchedule的请求
if(sdb==NULL||sdb->sections==NULL)...{
TRACE("EPG::Request(%d.%d.%d) ",svr->netId,svr->tsId,svr->serviceId);
//RequestEPG(svr,REQUEST_EITSCH);
rc=0;
}else...{
rc=UpdateScheduleInfo(hSch,sdb,tci.lParam);
UnlockScheduleDB(svr);//PlayByService会自动发送接收EITSchedule的请求
}
}
return rc;
}
static LRESULT WINAPI EpgWndProc(HWND hwnd,UINT msgID,WPARAM wParam,LPARAM lParam)
... {
switch(msgID)
...{
case WM_TIMER:
...{
char sdate[128],stime[64];
SYSTEMTIME tnow;
GetLocalTime(&tnow);
GetDateFormat(LOCALE_NEUTRAL,0,&tnow,0,sdate,64);
GetTimeFormat(LOCALE_NEUTRAL,TIME_NOSECONDS|TIME_FORCE24HOURFORMAT,&tnow," hh:mm tt",stime,64);
strcat(sdate,stime);
SetDlgItemText(hwnd,IDC_DATETIME,sdate);
}
break;
case WM_COMMAND:
...{
switch(wParam)
...{
case MAKELONG(IDC_SVCGROUPS,OPN_SELCHANGE)://分组改变事件处理
...{
INT idx=SendMessage((HWND)lParam,OPT_GETCURSEL,0,0);
FAVGROUP*fav=(FAVGROUP*)SendMessage((HWND)lParam,OPT_GETITEMDATA,idx,0);
HWND hs=GetDlgItem(hwnd,IDC_GRPSERVICE);
GetAllService(hs,(FAVGROUP*)fav);
}
break;
case MAKELONG(IDC_WEEK,OPN_SELCHANGE)://分组改变事件处理
TRACE("WEEK CHANGE ");
//pass throught
case MAKELONG(IDC_GRPSERVICE,LBN_SELCHANGE)://Service切换事件处理
DoServiceChange(hwnd);
break;
default:
break;
}
}break;
case WM_DRAWITEM:
...{
DRAWITEMSTRUCT *ds=(DRAWITEMSTRUCT*)lParam;
HDC hdc=(HDC)ds->hDC;
RECT rc=ds->rcItem;
char text[128];
HBRUSH hbBorder;
HDC hmdc=CreateCompatibleDC((HDC)hdc);
if(ds->CtlType==ODT_LISTBOX)
...{
HBRUSH hb;
HBRUSH hbBorder=CreateSolidBrush(RGB(214,247,255));
HRGN hrgn=CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom,0,0);
if(ds->itemState&ODS_SELECTED)...{
if(ds->itemState&ODS_FOCUS)
hb=CreateSolidBrush(RGB(207,99,22));
else
hb=CreateSolidBrush(RGB(255,255,181));
}else
hb=CreateSolidBrush(RGB(24,141,185));
FillRgn(hdc,hrgn,hb);
FrameRgn(hdc,hrgn,hbBorder,0,2);
SendMessage(ds->hwndItem,LB_GETTEXT,ds->itemID,(LPARAM)text);
SetBkMode(hdc,TRANSPARENT);
SetTextColor(hdc,RGB(0,0,0));
DrawText(hdc,text,sizeof(text),&rc,DT_VCENTER|DT_SINGLELINE|DT_LEFT);
SendMessage(ds->hwndItem,LB_GETITEMDATA,ds->itemID,0);
DeleteObject((HGDIOBJ)hb);
DeleteObject((HGDIOBJ)hrgn);
DeleteObject((HGDIOBJ)hbBorder);
}
DeleteDC(hmdc);
}
return 0;
case WM_ERASEBKGND:
...{
HDC hmdc=CreateCompatibleDC((HDC)wParam);
HBRUSH hbBorder;
//画菜单背景
hbBorder=CreateSolidBrush(RGB(61,185,197));
FillRect((HDC)wParam,NULL,hbBorder);
DeleteObject((HGDIOBJ)hbBorder);
...{
RECT rc;
HBITMAP hbmpTitle;
HBRUSH hbrush;
BITMAP bmp;
hbmpTitle=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_WINTITLE));
hbrush=CreatePatternBrush(hbmpTitle);
GetObject((HGDIOBJ)hbmpTitle,sizeof(BITMAP),&bmp);
GetClientRect(hwnd,&rc);rc.bottom=rc.top+bmp.bmHeight;
FillRect((HDC)wParam,&rc,hbrush);
DeleteObject((HGDIOBJ)hbrush);
DeleteObject((HGDIOBJ)hbmpTitle);
hbmpTitle=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_WINHELP));
hbrush=CreatePatternBrush(hbmpTitle);
GetObject((HGDIOBJ)hbmpTitle,sizeof(BITMAP),&bmp);
GetClientRect(hwnd,&rc);rc.top=rc.bottom-bmp.bmHeight;
FillRect((HDC)wParam,&rc,hbrush);
DeleteObject((HGDIOBJ)hbrush);
DeleteObject((HGDIOBJ)hbmpTitle);
}
DeleteDC(hmdc);
}
return 0;
case WM_NOTIFY:
...{
NMHDR *nmhdr = (PVOID)lParam;
if(nmhdr->code==TCN_SELCHANGE)...{
DoServiceChange(hwnd);
}
if(nmhdr->idFrom ==IDC_EPGSCHEDULE)...{
if(nmhdr->code == NM_CUSTOMDRAW) ...{
NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
SYSTEMTIME stnow;
FILETIME ft;
switch(nmlvcd->nmcd.dwDrawStage) ...{
case CDDS_PREPAINT:
return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT:
GetLocalTime(&stnow);
SystemTimeToFileTime(&stnow,&ft);
if(nmlvcd->nmcd.lItemlParam<ft.dwLowDateTime)...{
if(nmlvcd->nmcd.uItemState!=0)
nmlvcd->clrTextBk =CLR_DEFAULT;
else...{
nmlvcd->clrTextBk =RGB(200,200,200);
}
return CDRF_DODEFAULT;
}
return CDRF_NOTIFYSUBITEMDRAW;
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
if(nmlvcd->nmcd.dwItemSpec%2)...{
nmlvcd->clrTextBk =CLR_DEFAULT;
}else
nmlvcd->clrTextBk =RGB(200,200,250);
return CDRF_NOTIFYPOSTPAINT;
case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
if(nmlvcd->iSubItem==3)...{
BITMAP bmp;
RECT rc=nmlvcd->nmcd.rc;
HBITMAP hobmp,hbm=LoadBitmap(hInstDVBRes,MAKEINTRESOURCE(IDB_CLOCK));
HDC hmdc=CreateCompatibleDC(nmlvcd->nmcd.hdc);
hobmp=(HBITMAP)SelectObject(hmdc,(HGDIOBJ)hbm);
GetObject((HGDIOBJ)hbm,sizeof(BITMAP),&bmp);
BitBlt(nmlvcd->nmcd.hdc,rc.left,
rc.top+(RECTH(&rc)-bmp.bmHeight)/2,24,24,hmdc,0,0,SRCCOPY);
SelectObject(hmdc,(HGDIOBJ)hobmp);
DeleteObject((HGDIOBJ)hbm);
DeleteDC(hmdc);
return CDRF_SKIPDEFAULT;
}
return CDRF_DODEFAULT;
}
return CDRF_DODEFAULT;
}else if(nmhdr->code==LVN_ITEMCHANGED)...{
LPNMLISTVIEW lv=(LPNMLISTVIEW)lParam;
SetWindowLong(lv->hdr.hwndFrom,GWL_USERDATA,lv->iItem);
}else if(nmhdr->code==LVN_KEYDOWN)...{
LPNMLVKEYDOWN lk=(LPNMLVKEYDOWN)lParam;
CHAR desc[256];
LVITEM itm;
itm.mask=LVIF_TEXT;
itm.iItem=GetWindowLong(lk->hdr.hwndFrom,GWL_USERDATA);
itm.iSubItem=3;
itm.pszText=desc;
itm.cchTextMax=256;
ListView_GetItem(lk->hdr.hwndFrom,&itm);
if(lk->wVKey==VK_RETURN)
MessageBox(hwnd,desc,"节目简介",0);
}
}
}break;
case WM_DESTROY:
DeleteObject((HGDIOBJ)hbmpClock);
return DefWindowProc(hwnd,msgID,wParam,lParam);
case WM_CLOSE:
PrVideoSetOutputWindow(0,0,720,576);
//RegisterEPGNotify(NULL);
DefWindowProc(hwnd,msgID,wParam,lParam);
break;
case WM_ACTIVATE:
if(wParam)...{
RECT rc;
GetWindowRect(GetDlgItem(hwnd,IDC_VIDEO),(LPRECT)&rc);
PrVideoSetOutputWindow(rc.left,rc.top,RECTW(&rc),RECTH(&rc));
}
return DefWindowProc(hwnd,msgID,wParam,lParam);
default:
return DefWindowProc(hwnd,msgID,wParam,lParam);
}
return 0;
}
static void CreateListView(HWND hwnd, int count)
... {
int i;
LVCOLUMN lc;
char *titles[]=...{"开始时间","片长","片名","预定","节目介绍"};
int width[]=...{120,160,220,60,100};
//WS_EX_DLGMODALFRAME和LVS_EX_GRIDLINES定义存在冲突,会导致NC区域边框出现问题
HWND hv=CreateWindowEx(LVS_EX_FULLROWSELECT/**//*|LVS_EX_GRIDLINES*/,"ListView",NULL,
WS_TABSTOP|WS_CHILD|WS_VSCROLL|WS_VISIBLE|LVS_SHOWSELALWAYS//|LVS_SINGLESEL
|LVS_REPORT|LVS_NOCOLUMNHEADER,//|LVS_OWNERDRAWFIXED|,
36,286,582,175,hwnd,(HMENU)IDC_EPGSCHEDULE,NULL,NULL);
for(i=0;i<sizeof(titles)/sizeof(char*);i++)
...{
lc.pszText=titles[i];
lc.cx=width[i];
lc.mask=LVCF_TEXT|LVCF_WIDTH|LVCF_FMT;
lc.fmt=i==0?LVCFMT_RIGHT:LVCFMT_LEFT;
SendMessage(hv,LVM_INSERTCOLUMN,i,(LPARAM)&lc);
}
}
HWND CreateEpgWnd(UINT grpId)
... {
int i;
HWND ch,DispWin;
SYSTEMTIME tnow;
HWND epgWnd;
HWND hg;
HWND htab;
epgWnd = CreateMainWindow(NULL,WS_TABSTOP|WS_OVERLAPPED,40,30,650,520,EpgWndProc);
GetLocalTime(&tnow);
CreateWindow("Static",NULL,WS_VISIBLE|WS_CHILD|SS_LEFT,//|SS_OWNERDRAW,
350,13,290,25,epgWnd,(HMENU)IDC_DATETIME,NULL,NULL);
//标题
CreateWindow("Static","节 目 指 南",WS_VISIBLE|WS_CHILD,//|SS_OWNERDRAW,
40,13,200,24,epgWnd,(HMENU)IDC_TITLE,NULL,NULL);
hg=CreateWindow("Select",NULL,WS_VISIBLE|WS_CHILD|WS_BORDER|
OPS_SHOWARROWALWAYS|OPS_NOLABEL|WS_DISABLED,//(grpId==0xFFFFFFFF?0:WS_DISABLED),
35,60,325,27,epgWnd,(HMENU)IDC_SVCGROUPS,NULL,NULL);
if (NULL != hg)
...{
FAVGROUP*fav;
CreateDefaultGroup(FALSE);
UpdateAllGroup();
fav=GetFirstFavGroup();//添加分组数据
for(i=0;fav;fav=fav->next,i++)...{
INT idx;
idx=SendMessage(hg,OPT_ADDSTRING,i,(LPARAM)fav->name);
SendMessage(hg,OPT_SETITEMDATA,idx,fav);
if(grpId==0xFFFF)
SendMessage(hg,OPT_SETCURSEL,0,(LPARAM)0);
else if(grpId==fav->FavId)
SendMessage(hg,OPT_SETCURSEL,idx,0);
}
}
ch=CreateWindow("Listbox",NULL,WS_TABSTOP|WS_VSCROLL|WS_VISIBLE|WS_CHILD|
LBS_OWNERDRAWFIXED|LBS_HASSTRINGS|LBS_NOTIFY|LBS_WRAP,
35,96,325,150,epgWnd,(HMENU)IDC_GRPSERVICE,NULL,NULL);
if (NULL != ch)
...{
FAVGROUP*fav;
fav=FindFavGroupByID(grpId==0xFFFF?GROUP_ALL:grpId);
//添加业务数据
GetAllService(ch,fav);
SendMessage(ch,LB_SETITEMHEIGHT,0,30);
SendMessage(ch,LB_SETCURSEL,0,0);
}
//电视窗口
DispWin=CreateWindow("Static",NULL,WS_VISIBLE|WS_CHILD|SS_OWNERDRAW,
370,60,250,178,epgWnd,(HMENU)IDC_VIDEO,NULL,NULL);
//将电视窗口变为圆角矩形
...{
RECT rc;
HRGN rgn;
GetWindowRect(DispWin,(LPRECT)&rc);
rgn=CreateRoundRectRgn(0,0,RECTW(&rc),RECTH(&rc),10,10);
SetWindowRgn(DispWin,rgn,FALSE);
DeleteObject((HGDIOBJ)rgn);
}
htab=CreateWindow("tabcontrol",NULL,WS_VISIBLE|WS_TABSTOP|WS_CHILD|TCS_BUTTONS|TCS_HOTTRACK|TCS_FOCUSONBUTTONDOWN,//|TCS_OWNERDRAWFIXED,
36,258,582,27,epgWnd,(HMENU)IDC_WEEK,NULL,NULL);
if(NULL != htab)
...{
TCITEM itm;
int i;
GetLocalTime(&tnow);
itm.mask=TCIF_TEXT|TCIF_PARAM;
for (i=0; i<7; i++)...{
CHAR wname[32];
GetLocaleInfo(LOCALE_NEUTRAL,
tnow.wDayOfWeek==0?LOCALE_SDAYNAME7:(LOCALE_SDAYNAME1+tnow.wDayOfWeek-1),wname,32);
itm.lParam=tnow.wDayOfWeek;
tnow.wDayOfWeek=(tnow.wDayOfWeek+1)%7;
itm.pszText = wname;
TabCtrl_InsertItem(htab,i,&itm);
}
SendMessage(htab,TCM_SETCURSEL,0,0);
}
CreateListView(epgWnd,100);
...{
TBBUTTON toolbarBtns[] = ...{
...{0, 0, 0, BTNS_SEP, ...{0, 0}, 0, 0},
...{0, 123, TBSTATE_ENABLED,BTNS_BUTTON, ...{0, 0}, 0, "选择"},
...{1, 122, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, 0},
...{2, 133, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, "Test"},
...{3, 144, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, 0},
...{4, 145, TBSTATE_ENABLED, BTNS_BUTTON, ...{0, 0}, 0, 0},
...{5, 156, TBSTATE_ENABLED, BTNS_BUTTON|BTNS_DROPDOWN, ...{0, 0}, 0, 0},
};
HWND htoolbar=CreateToolbarEx(epgWnd, WS_CHILD|WS_VISIBLE|
TBSTYLE_LIST|TBSTYLE_TRANSPARENT|TBSTYLE_FLAT|CCS_BOTTOM,
1234, 2, hInstDVBRes, IDB_COLORKEYS, toolbarBtns,
sizeof(toolbarBtns)/sizeof(TBBUTTON), 36, 18, 36, 18, sizeof(TBBUTTON));
SendMessage(htoolbar,TB_SETEXTENDEDSTYLE,0, TBSTYLE_EX_DRAWDDARROWS);
}
ShowWindow(epgWnd,SW_SHOW);
//SetFocus(GetDlgItem(epgWnd,IDC_GRPSERVICE));
SetTimer(epgWnd,IDT_EPGTIMER,1000,NULL);
return epgWnd;
}