為了實踐工程數學中,傅立葉變換用於音頻處理的技術,在Matlab的作法早已了然於心,但不用他人數學庫、不用C++自己幹一個算法實作出來
就是不痛快。
因此,特地去翻了翻Windows關於音訊處理的流程以及方法,貌似現在windows關於多媒體處理的技術現在都用Microsoft Media Foundation來實踐了。
快速理解該技術架構後,開始查找相關資源並進行理解,沒想到MSDN上的相關範例竟然有不少函式是被deprecated的,真差點沒被氣死。
這裡有坑,因此在此提醒各位看官。
花了不少時間後才終於在windows7SDK中找到"合適"範例代碼。SDK範例代碼現在可以從GITHUB直接下載,連結網址。
Microsoft Media Foundation 的MFPlayer範例中,有段特殊的代碼是之前沒看過的。
// Initialize the common control library.
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_STANDARD_CLASSES | ICC_BAR_CLASSES;
if (!InitCommonControlsEx(&icc))
{
MessageBox(NULL, L"InitCommonControlsEx failed.", NULL, MB_ICONSTOP);
CoUninitialize();
return 0;
}
之後一查,原來windows還有為一些特別控件進行動態函示庫包裝,能讓人快速調用。
這裡來做些展示。
像這種下載動畫:
或是像這種菜單欄
心動不?以前像這種控件都是自己手刻的,不然就是要套用其他人的庫,現在才知道Windows有這麼好用的庫,
真是相見恨晚。
迫不及待想快速掌握用法了。
先來附上一的Msdn關於 common control的連結:https://msdn.microsoft.com/zh-tw/library/windows/desktop/bb775493(v=vs.85).aspx
接著就跟以前一樣,直接從閱讀代碼來學習它的用法。
以下也是筆者一邊看代碼,一邊學習並記錄。
這是連結所需要的庫,及頭文件。
#include <commctrl.h>
#pragma comment(lib, "comctl32.lib")
這是程序進入點,其中 IDD_MAINDIALOG是主視窗樣板資源,DialogProc是該視窗回調函數。
int APIENTRY wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow)
{
g_hInst = hInstance;
return DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, DialogProc);
}
這是 DialogProc實現,用於對各類信息進行轉發,由上到下分別是初始化窗口信息,及菜單欄信息、窗口關閉信息。
HANDLE_MSG其實是個宏,宏定義長得像這樣:
#define HANDLE_MSG(hwnd, message, fn) \
case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))
就是做了一層信息轉發。
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// Handle the WM_INITDIALOG message in OnInitDialog
HANDLE_MSG (hWnd, WM_INITDIALOG, OnInitDialog);
// Handle the WM_COMMAND message in OnCommand
HANDLE_MSG (hWnd, WM_COMMAND, OnCommand);
// Handle the WM_CLOSE message in OnClose
HANDLE_MSG (hWnd, WM_CLOSE, OnClose);
default:
return FALSE;
}
return 0;
}
OnInitDialog 進去發現只有return true;
而OnCommand長得像以下代碼,針對類型按鈕的回調函數
void OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
{
switch (id)
{
case IDC_BUTTON_ANIMATION:
{
HWND hDlg = CreateDialog(g_hInst,
MAKEINTRESOURCE(IDD_ANIMATIONDIALOG),
hWnd, AnimationDlgProc);
if (hDlg)
{
ShowWindow(hDlg, SW_SHOW);
}
}
break;
case IDC_BUTTON_COMBOBOXEX:
{
HWND hDlg = CreateDialog(g_hInst,
MAKEINTRESOURCE(IDD_COMBOBOXEXDIALOG),
hWnd, ComboBoxExDlgProc);
if (hDlg)
{
ShowWindow(hDlg, SW_SHOW);
}
}
break;
case IDC_BUTTON_DATETIMEPICK:
{
HWND hDlg = CreateDialog(g_hInst,
MAKEINTRESOURCE(IDD_DATETIMEPICKDIALOG),
hWnd, DateTimePickDlgProc);
if (hDlg)
{
ShowWindow(hDlg, SW_SHOW);
}
}
break;
.....省略.....
IDC_BUTTON_ANIMATION進去後可以看見在貼文章下載動畫。
CreateDialog是依造資源項創建視窗,而重點在於AnimationDlgProc 這個回調函數。
AnimationDlgProc其實又是一層消息轉發函數。
INT_PTR CALLBACK AnimationDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
// Handle the WM_INITDIALOG message in OnInitAnimationDialog
HANDLE_MSG (hWnd, WM_INITDIALOG, OnInitAnimationDialog);
// Handle the WM_CLOSE message in OnClose
HANDLE_MSG (hWnd, WM_CLOSE, OnClose);
default:
return FALSE; // Let system deal with msg
}
return 0;
}
這總算是真正實現代碼的位置了,當子窗口生成時會自動執行以下代碼。
BOOL OnInitAnimationDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam)
{
// Load and register animation control class.
INITCOMMONCONTROLSEX iccx = { sizeof(iccx) };
iccx.dwICC = ICC_ANIMATE_CLASS;
if (!InitCommonControlsEx(&iccx))
{
return FALSE;
}
// Create the animation control.
RECT rc = { 20, 20, 280, 60 };//在子窗口中又創建控件window用於跑動畫
HWND hAnimate = CreateWindowEx(0, ANIMATE_CLASS, 0,
ACS_TIMER | ACS_AUTOPLAY | ACS_TRANSPARENT | WS_CHILD | WS_VISIBLE,
rc.left, rc.top, rc.right, rc.bottom,
hWnd, reinterpret_cast<HMENU>(IDC_ANIMATION), g_hInst, 0);
if (hAnimate == NULL)
{
return FALSE;
}
// Open the AVI clip and display its first frame in the animation control.
if (0 == SendMessage(hAnimate, ACM_OPEN, static_cast<WPARAM>(0),
reinterpret_cast<LPARAM>(MAKEINTRESOURCE(IDR_UPLOAD_AVI))))
{
return FALSE;
}
// Plays the AVI clip in the animation control.
if (0 == SendMessage(hAnimate, ACM_PLAY, static_cast<WPARAM>(-1),
MAKELONG(/*from frame*/0, /*to frame*/-1)))
{
return FALSE;
}
return TRUE;
}
其中,在Create window時,ANIMATE_CLASS及後面不曾見過的Style宣告在在我們一開始引入的頭文件裡
SendMessage(hAnimate, ACM_OPEN, static_cast<WPARAM>(0),
reinterpret_cast<LPARAM>(MAKEINTRESOURCE(IDR_UPLOAD_AVI))
發現了一件不得了的事,原來剛剛的實踐,只有完成動畫播放器而已,真正的動畫資源還是要自己引入的,
如本次中,為IDR_UPLOAD_AVI。
還有其他common control範例,可以直接參考連結:https://code.msdn.microsoft.com/windowsapps/CppWindowsCommonControls-9ea0de64
而我自己看完這一系列api後,打算自己時做一個相似的效果,來加深印象。在範例的最末尾發現他給的參考連結: https://msdn.microsoft.com/en-us/library/bb761881.aspx