本BLOG所有原創之原始程式碼皆為本人創作,非經本人同意不得轉載,非經本人授權不得使用在營利用途
資源正規化及圖像工廠
在上一篇中 点击打开链接 只是先把2個關鍵的Decoder 的實作,與相關的 INTERFACE POST 出來 ,至於要如何用在此要先說明一個觀念,
這也是這個 XML BASE 的人機介面引擎中極為重要的事,資源正規化在我簡介資源正規化前我先給大家看一下,已完成後的引擎,他所用的 XML 是如何寫的
Multimedia.XML
<?xml version="1.0" encoding="utf-8" ?>
<root boot="main" >
<dialog id="Multimedia" fullsize="1" url="\resource\Multimedia" background="img://Multimedia-Multimedia.png" font="Arial" font-width="5" font-height="18" font-color="16777215" font-weight="600" >
<controls>
<text value="@16" style="left" top="0" left="8" right="160" bottom="24" />
<clock top="8" left="348" right="435" bottom="24" font="Arial" font-width="6" font-height="18" font-color="16777215" font-weight="600" />
<battery id="battery" proxy="battery" top="5" left="434" right="475" bottom="27" />
<button top="70" left="15" text-top="190" text-bottom="218" value="@17" normal="img://Multimedia-135.png" active="img://Multimedia-135-a.png" οnclick="#window.Navigate('resource\music.xml','music')"/>
<button top="70" left="135" text-top="190" text-bottom="218" value="@44" normal="img://Multimedia-136.png" active="img://Multimedia-136-a.png" οnclick="#window.Navigate('resource\video.xml','video')"/>
<button top="70" left="245" text-top="190" text-bottom="218" value="@63" normal="img://Multimedia-137.png" active="img://Multimedia-137-a.png" οnclick="#window.Navigate('resource\photo.xml','photo')"/>
<button top="70" left="370" text-top="190" text-bottom="218" value="@79" normal="img://Multimedia-138.png" active="img://Multimedia-138-a.png" οnclick="#window.closewindow(0)"/>
</controls>
</dialog>
</root>
這篇就是其中的一頁,用在一些Multimedia功能的設定,其他的 tag 都先不用管 ,我們先注意2點
1. url="\resource\Multimedia"
2. background="img://Multimedia-Multimedia.png"
有沒有注意到url="\resource\Multimedia",這是表示,這個 dialog 所用的資源在預設下都由"\resource\Multimedia"這目錄去找
所以當引擎看到 background 時便知道背景圖是去找 "\resource\Multimedia\Multimedia-Multimedia.png"
而如果沒定url 引擎便以父 dialog的url去找,一直找到根,如果連根的url也是沒定義,便以引擎預設值為url
而 img:// 便是型態工廠部份 ,當引擎看到background便以img://Multimedia-Multimedia.png去問型態工廠,
而型態工廠因為知道是background 而且是以圖型為主,便直接引至繪圖引擎,繪圖引擎便分析img://Multimedia-Multimedia.png,
知道要去找img 類別的decoder,於是便把imgdecoder載入,把Multimedia-Multimedia.png的完整路徑交給imgdecoder去load,這便是圖像工廠的觀念
而明定 url 資源的位置的表示規則,便是資源正規化的觀念
說了多那麼我們就直接看一下這部份的實作碼
CComPtr<IHLXImage> CBackground::CreateImage( LPCWSTR lpCommand ,LONG lAlpha )
{
WCHAR buff[MAX_PATH];
VARIANT_BOOL varRet;
CComPtr<IHLXImage> spImage;
#ifdef _DEBUG
DWORD clk=::GetTickCount();
#endif
if( ParseUrl(lpCommand,buff,MAX_PATH) )
{
if( CreateImageObject(lpCommand,&spImage) == true )
{
spImage->put_AlphaMode(lAlpha);
if( SUCCEEDED(spImage->load(buff,&varRet)) && varRet == VARIANT_TRUE )
{
CComPtr<IHLXAnimation> spAnimation;
if( SUCCEEDED(spImage.QueryInterface(&spAnimation)) )
{
LONG count;
if( spAnimation->frameCount(&count) == S_OK && count > 2 )
SetTimeClick(10);
}
#ifdef _DEBUG
m_dwCreateImageTickCount += ::GetTickCount()-clk;
#endif
return spImage;
}
#ifdef _DEBUG
m_dwCreateImageTickCount += ::GetTickCount()-clk;
#endif
}
}
return NULL;
}
bool CCommonUtility::ParseUrl( LPCWSTR lpUrlName ,LPCWSTR lpTage ,LPWSTR buff ,UINT length )
{
DWORD dwUrl,dwTage;
LPCWSTR pTargetName;
if( ((dwUrl=wcslen(lpUrlName)) + (dwTage=wcslen(lpTage))) < length )
{
if( (pTargetName=wcsstr(lpTage,OLESTR("://"))) )
{
pTargetName += 3;
wcscpy(buff,lpUrlName);
buff[dwUrl] = OLECHAR('\0');
if( *pTargetName == WCHAR('/') )
{
wcscat(buff,pTargetName+1);
dwTage--;
}
else
wcscat(buff,pTargetName);
buff[dwUrl+dwTage] = OLECHAR('\0');
return true;
}
}
return false;
}
bool CCommonUtility::CreateImageObject(LPCWSTR lpFullName ,IHLXImage** ppImage )
{
CComPtr<IHLXImage> pImage;
LPCWSTR key=OLESTR("HLXLib.Typeinfo\\.");
WCHAR type[25],value[MAX_PATH];
LPCWSTR lpName;
CRegKey hkey;
ULONG dwLength;
#ifdef _DEBUG
DWORD clk=::GetTickCount();
#endif
::wmemset(type,0,sizeof(type)/sizeof(WCHAR));
if( (lpName=wcsstr(lpFullName,OLESTR("://"))) != NULL && (lpName-lpFullName) == 3 )
{
dwLength = MAX_PATH;
wmemcpy( type ,key ,wcslen(key));
wmemcpy( type+wcslen(key) ,lpFullName ,3);
if( hkey.Open(HKEY_CLASSES_ROOT,type) == ERROR_SUCCESS && hkey.QueryStringValue(L"",value,&dwLength) == ERROR_SUCCESS )
{
if( SUCCEEDED(pImage.CoCreateInstance(value)) && pImage != NULL )
{
*ppImage=pImage.Detach();
#ifdef _DEBUG
m_dwImageTickCount += ::GetTickCount()-clk;
#endif
return true;
}
}
}
#ifdef _DEBUG
m_dwImageTickCount += ::GetTickCount()-clk;
#endif
return false;
}
上面便是圖像工廠的實作部份,很簡單對不對
也許有人不能理解為什麼上面的碼有辦法正確找的到img 對映的decoder,其實關鍵是在
LPCWSTR key=OLESTR("HLXLib.Typeinfo\\."); 這行碼,還不了解嗎?
我們再看一個檔 IMGDecoder.rgs
HKCR
{
HLXDocvw.IMGDecoder.1 = s 'IMGDecoder Class'
{
CLSID = s '{11D7BE59-D81D-48D3-A551-B9EB208F0123}'
}
HLXDocvw.IMGDecoder = s 'IMGDecoder Class'
{
CLSID = s '{11D7BE59-D81D-48D3-A551-B9EB208F0123}'
CurVer = s 'HLXDocvw.IMGDecoder.1'
}
NoRemove CLSID
{
ForceRemove {11D7BE59-D81D-48D3-A551-B9EB208F0123} = s 'IMGDecoder Class'
{
ProgID = s 'HLXDocvw.IMGDecoder.1'
VersionIndependentProgID = s 'HLXDocvw.IMGDecoder'
ForceRemove 'Programmable'
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Both'
}
val AppID = s '%APPID%'
'TypeLib' = s '{35CEFEE5-2058-4A33-B234-89AD330B5AD0}'
}
}
NoRemove HLXLib.Typeinfo
{
.img = s 'HLXDocvw.IMGDecoder'
}
}
這個是一般 ATL 會幫你產生的一個註冊檔,用來去登註去 Windows系統,這個COM才能正常使用,但是最後一段卻不像是ATL加入的?
沒錯!
{.img = s 'HLXDocvw.IMGDecoder'}
便是用來關連的部份,decoder 只要在註冊檔加入這段,圖像工廠便會去 HLXLib.Typeinfo 下找有沒有 img 這類別的decoder存在,如果找到
便用登註的progid 去建出 HLXDocvw.IMGDecoder ,並用IHLXImage界面把完整路徑交給IHLXImage去load,
像有人會問如果要用到 GIF,可是如果 img沒有 GIF的解碼,那這引擎不就是癈物一個?
別急,由 imgdecoder 同理可知,只要寫出一個decoder ,依引擎定的規則去註冊,再提供IHLXImage 給引擎叫用,不就GIF可以解碼
所以只要有了圖像工廠不管以後有什麼新的圖像格式,只要寫個decoder再登註,引擎就有辦法把這個圖檔正確讀出,這便是把 Decoder 裝置化的過程好了解釋完繪圖引擎如何把已知未知的圖片讀取整合的方式後,下篇再分別解釋 IHLXImage系列INTERFACE 和繪圖引擎的關係