admin 发布的文章

Rollout控件在3DMAX上很多,在界面显示有很大的便利,既可以展开,又可以收起,

WTL下有一个相应的模拟实现,在codeproject中有其源码:

https://www.codeproject.com/Articles/1351/WTL-Rolldown-Control

但示例仅在SDI中有,要应用到Dialog中,还需要做一番调整。

在OnInitDialog中创建窗口:

LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
//center the dialog on the screen CenterWindow();//set icons HICON hIcon =AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
SetIcon(hIcon, TRUE);
HICON hIconSmall
=AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
SetIcon(hIconSmall, FALSE);

m_RolloutContainer.Create(m_hWnd);
dlg1.Create(m_RolloutContainer.m_hWnd, _T(
"Rollout Control 1"));
dlg1.ShowWindow(SW_SHOWNORMAL);
m_RolloutContainer.AddRollout(dlg1);
dlg2.Create(m_RolloutContainer.m_hWnd, _T("Rollout Control 2"));
dlg2.ShowWindow(SW_SHOWNORMAL);
m_RolloutContainer.AddRollout(dlg2);
m_RolloutContainer.ShowWindow(SW_SHOWNORMAL);
returnTRUE;
}

对话框类中声明如下:

#include "AtlRollOutCtrl.h"#include"TestDlg.h"

class CMainDlg : public CDialogImpl<CMainDlg>{public:enum { IDD =IDD_MAINDLG };//CPaneContainer  m_PropPane;
CRolloutContainerClient m_RolloutContainer;
CRolloutCtrl<CDlg1> dlg1;
CRolloutCtrl<CDlg2> dlg2;

关键实现如下:

1.Dialog类实现WM_SIZE消息处理:

BEGIN_MSG_MAP(CMainDlg)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
END_MSG_MAP()

OnSize的实现体内容(拷贝、修改自CFrameWindowImpl):

    LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL&bHandled)
{
if(wParam !=SIZE_MINIMIZED)
{
CMainDlg
* pT = static_cast<CMainDlg*>(this);
pT->
UpdateLayout();
}
bHandled
=FALSE;return 1;
}

相应的UpdateLayout是关键实现:

    void UpdateLayout(BOOL bResizeBars =TRUE)
{
RECT rect;
GetClientRect(
&rect);//resize client window if(m_RolloutContainer.m_hWnd != NULL && ::IsWindowVisible(m_RolloutContainer.m_hWnd) ==TRUE)
{
SIZE ctrlSize;
m_RolloutContainer.GetClientSize(
&ctrlSize);int cx =ctrlSize.cx;
RECT rc;
rc
=rect;//rect.right -= cx;//rc.bottom -= 40;//rc.left = rect.right; m_RolloutContainer.SetWindowPos(NULL, rc.left, rc.top,
rc.right
- rc.left, rc.bottom -rc.top,
SWP_NOZORDER
|SWP_NOACTIVATE);
}
}

其实,就是取得客户区大小,将Rollout容器占满整个客户区。示例对话框截图如下:

 

 AtlRollOutCtrl.h文件,在WTL10时,有两处需要修改

 

 

 

 

目前还有一个BUG待修复,对话框可调整大小时,如调整大小,Rollout的右边滚动条会画花屏幕,刷新后OK,待解决

 

视频帧双缓冲区的第一个版本,仅缓冲视频帧,CSharedCriticalSection是临界区保护类

classCFrameCache{public:
CFrameCache()
: pop_frame_ptr_(nullptr)
, push_frame_ptr_(nullptr)
, width_(
0), hight_(0), channels_(0){

}
~CFrameCache() {if(pop_frame_ptr_) {delete[] pop_frame_ptr_;
pop_frame_ptr_
=nullptr;
}
if(push_frame_ptr_){delete[] push_frame_ptr_;
push_frame_ptr_
=nullptr;
}
}
void push_frame(const char* frame, int width, int hight, intchannels){if(nullptr == frame || width < 0 || hight < 0 || channels < 0) {return;
}

CSharedMutex
lock(mutex_);if(push_frame_ptr_ == nullptr &&pop_frame_ptr_==nullptr) {
width_
=width;
hight_
=hight;
channels_
=channels;
pop_frame_ptr_
= new char[width_ * hight_ *channels_];
push_frame_ptr_
= new char[width_ * hight_ *channels_];
memset(pop_frame_ptr_,
0x00, width_ * hight_ *channels_);
memset(push_frame_ptr_,
0x00, width_ * hight_ *channels_);
}
if((width != width_ || hight_ != hight || channels_ != channels) && push_frame_ptr_ &&pop_frame_ptr_) {
width_
=width;
hight_
=hight;
channels_
=channels;delete[] pop_frame_ptr_;delete[] push_frame_ptr_;
pop_frame_ptr_
= new char[width_ * hight_ *channels_];
push_frame_ptr_
= new char[width_ * hight_ *channels_];

memset(pop_frame_ptr_,
0x00, width_ * hight_ *channels_);
memset(push_frame_ptr_,
0x00, width_ * hight_ *channels_);
}

memset(push_frame_ptr_,
0x00, width_ * hight_ *channels_);
memcpy(push_frame_ptr_, frame, width_
* hight_ *channels_);
}
const char*pop_frame(){
CSharedMutex
lock(mutex_);
std::swap(push_frame_ptr_, pop_frame_ptr_);
returnpop_frame_ptr_;
}
intsize(){
CSharedMutex
lock(mutex_);return width_ * hight_ *channels_;
}
intWidth() {
CSharedMutex
lock(mutex_);returnwidth_;
}
intHight() {
CSharedMutex
lock(mutex_);returnhight_;
}
intChannels() {
CSharedMutex
lock(mutex_);returnchannels_;
}
protected:
CFrameCache(
const CFrameCache&rhs){

}

CFrameCache
& operator=(const CFrameCache&rhs){return *this;
}
private:char*pop_frame_ptr_;char*push_frame_ptr_;intwidth_, hight_, channels_;
CSharedCriticalSection mutex_;
};

视频帧双缓冲区的第二个版本,缓冲视频帧,并允许保存一些视频的附加信息

//带EXIF信息的帧缓冲
template <typename ExifClass>
classCFrameCacheWithExif{public:
CFrameCacheWithExif()
: pop_frame_ptr_(nullptr)
, push_frame_ptr_(nullptr)
, width_(
0), hight_(0), channels_(0){

}
~CFrameCacheWithExif() {if(pop_frame_ptr_) {delete[] pop_frame_ptr_;
pop_frame_ptr_
=nullptr;
}
if(push_frame_ptr_){delete[] push_frame_ptr_;
push_frame_ptr_
=nullptr;
}
if(pop_exif_ptr_) {delete[] pop_exif_ptr_;
pop_exif_ptr_
=nullptr;
}
if(push_exif_ptr_){delete[] push_exif_ptr_;
push_exif_ptr_
=nullptr;
}
}
void push_frame(const char* frame, const void* exif, int width, int hight, intchannels){if(nullptr == frame || width < 0 || hight < 0 || channels < 0) {return;
}

CSharedMutex
lock(mutex_);if(push_frame_ptr_ == nullptr &&pop_frame_ptr_==nullptr) {
width_
=width;
hight_
=hight;
channels_
=channels;
pop_frame_ptr_
= new char[width_ * hight_ *channels_];
push_frame_ptr_
= new char[width_ * hight_ *channels_];
memset(pop_frame_ptr_,
0x00, width_ * hight_ *channels_);
memset(push_frame_ptr_,
0x00, width_ * hight_ *channels_);

pop_exif_ptr_
= new unsigned char[sizeof(ExifClass)];
push_exif_ptr_
= new unsigned char[sizeof(ExifClass)];
memset(pop_exif_ptr_,
0x00, sizeof(ExifClass));
memset(push_exif_ptr_,
0x00, sizeof(ExifClass));
}
if((width != width_ || hight_ != hight || channels_ != channels) && push_frame_ptr_ &&pop_frame_ptr_) {
width_
=width;
hight_
=hight;
channels_
=channels;delete[] pop_frame_ptr_;delete[] push_frame_ptr_;
pop_frame_ptr_
= new char[width_ * hight_ *channels_];
push_frame_ptr_
= new char[width_ * hight_ *channels_];

memset(pop_frame_ptr_,
0x00, width_ * hight_ *channels_);
memset(push_frame_ptr_,
0x00, width_ * hight_ *channels_);delete[] pop_exif_ptr_;delete[] push_exif_ptr_;
pop_exif_ptr_
= new unsigned char[sizeof(ExifClass)];
push_exif_ptr_
= new unsigned char[sizeof(ExifClass)];
memset(pop_exif_ptr_,
0x00, sizeof(ExifClass));
memset(push_exif_ptr_,
0x00, sizeof(ExifClass));
}

memset(push_frame_ptr_,
0x00, width_ * hight_ *channels_);
memcpy(push_frame_ptr_, frame, width_
* hight_ *channels_);

memset(push_exif_ptr_,
0x00, sizeof(ExifClass));
memcpy(push_exif_ptr_, exif,
sizeof(ExifClass));
}
const char* pop_frame(void**exif){
CSharedMutex
lock(mutex_);
std::swap(push_frame_ptr_, pop_frame_ptr_);
std::swap(push_exif_ptr_, pop_exif_ptr_);
if (nullptr !=exif) {*exif =pop_exif_ptr_;
}
returnpop_frame_ptr_;
}
intsize(){
CSharedMutex
lock(mutex_);return width_ * hight_ *channels_;
}
intWidth() {
CSharedMutex
lock(mutex_);returnwidth_;
}
intHight() {
CSharedMutex
lock(mutex_);returnhight_;
}
intChannels() {
CSharedMutex
lock(mutex_);returnchannels_;
}
protected:
CFrameCacheWithExif(
const CFrameCacheWithExif&rhs){

}

CFrameCacheWithExif
& operator=(const CFrameCacheWithExif&rhs){return *this;
}
private:char*pop_frame_ptr_;
unsigned
char*pop_exif_ptr_;char*push_frame_ptr_;
unsigned
char*push_exif_ptr_;intwidth_, hight_, channels_;
CSharedCriticalSection mutex_;
};