Cómo dibujar datos de usuario en DuiLib
En DuiLib, a veces es necesario dibujar gráficos o imágenes en la ventana, como dibujar curvas relacionadas o procesar OpenCV los datos Mat de la imagen. En este momento, DuiLib no tiene una función directa para operar la interfaz. Este artículo describe un método de compromiso basado en Windows Win.
1. Defina la clase CWndUI para que pueda agregarse a DuiLib
clase CWndUI: public CControlUI
{
public:
CWndUI(): m_hWnd(NULL){}
virtual void SetVisible(bool bVisible = true)
{
__super: : SetVisible(bVisible);
::ShowWindow(m_hWnd, bVisible);
}
virtual void SetInternVisible(bool bVisible = true)
{
__super::SetInternVisible(bVisible);
::ShowWindow(m_hWnd, bVisible);
}
virtual void SetPos(RECT rc)
{
__super::SetPos(rc);
::SetWindowPos(m_hWnd, NULL, rc.left, rc arriba, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER SWP_NOACTIVATE);
}
BOOL Adjuntar(HWND hWndNew)
{
if (! ::IsWindow(hWndNew))
{
return FALSE;
}
m_hWnd = hWndNew;
devuelve VERDADERO;
}
HWND Detach()
{
HWND hWnd = m_hWnd;
m_hWnd = NULL;
devuelve hWnd;
}
HWND GetHWND()
{
return m_hWnd;
}
protegido:
HWND m_hWnd;
};
2. Definir y registrar ventanas y funciones de procesamiento de ventanas
ATOM MyRegisterWnd(TCHAR *szClsName, WNDPROC WndProc)
{WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcex.lpfnWndProc = WndProc;
wcex. cbClsExtra = 0;
wcex.cbWndExtra = 0;
p>
wcex.hInstance = GetModuleHandle(NULL);
wcex.hIcon = NULL;// LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TEST));
wcex.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = GetStockBrush(LTGRAY_BRUSH); //(HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL ;// MAKEINTRESOURCE(IDC_TEST);
wcex.lpszClassName = szClsName;
wcex.hIconSm = NULL;// LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); p> p>
return RegisterClassEx(&wcex);
}
La función de procesamiento de la ventana es:
LRESULT CALLBACK CallbackImageCalibration(HWND hWnd, mensaje UINT , WPARAM wParam , LPARAM lParam)
{
// int wmId, wmEvent
PAINTSTRUCT ps;
HDC hdc; hRedBrush;
static int cxClient, cyClient;
RECT rect;
HBRUSH hbrush;
cambiar (mensaje)
{
caso WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
: :PostMessage( hWnd, WM_PAINT, NULL, NULL);
return 0;
case WM_ERASEBKGND:
hdc = GetDC(hWnd);//Pagar cerca atención a las variables locales Si la CC no se obtiene aquí, el borrado fallará.
hbrush = CreateSolidBrush(RGB(0, 0, 0));//Crea un nuevo pincel
GetClientRect(hWnd, &rect);
FillRect( hdc , &rect, hbrush);
ReleaseDC(hWnd, hdc);
devuelve TRUE;
caso WM_PAINT:
hdc = BeginPaint (hWnd, &ps);
m_fc.DrawriginImage(hWnd); // m_fc es la clase de corrección de imagen de ojo de pez
EndPaint(hWnd, &ps);
romper;
predeterminado:
devolver DefWindowProc(hWnd, mensaje, wParam, lParam);
}
devolver 0;
}
Registrar la ventana en el programa principal
TCHAR szClsName[256] = _T("#32775");
MyRegisterWnd ( szClsName, CallbackImageCalibration);
3. Defina los elementos en el archivo XML de la interfaz DuiLib y créelo
< /HorizontalLayout >>p>
Crea una ventana llamada Wnd1
CControlUI* CFIPFrameWnd::CreateControl(LPCTSTR pstrClassName)
{
if (_tcsicmp ( pstrClassName, _T("Wnd1")) == 0)
{
CWndUI *pUI = nuevo CWndUI;
m_hwndImageCalibration = CreateWindow(_T(" # 32775"), _T("WndImageCalibration"), WS_VISIBLE | WS_CHILD, 0, 0, 0, 0, m_PaintManager.GetPaintWindow(), (HMENU)0, NULL, NULL);
pUI-> Adjuntar (m_hwndImageCalibration);
pUI->SetVisible(true);
::ShowWindow(m_hwndImageCalibration, true);
::UpdateWindow(m_hwndImageCalibration);
devolver pUI;
}
devolver pUI;
}
4. p >
Lo que se muestra aquí es una función para la corrección de imágenes de ojo de pez.
CControlUI *pbtnWnd = m_PaintManager.FindControl(_T("wndImageCalibration"));
pbtnWnd->SetVisible(true);
//Sigue el modo de DuiLib obtiene la clase de entidad del control
CListUI* pListUI = static_cast
int nSel = pListUI-> GetCurSel ();//Obtén el de la izquierda
m_fc.fix_data = NULL;//m_fc es la clase de corrección de imagen de ojo de pez
if (nSel >= 0)
{
string_t nombre de archivo = m_imageCalibrationList.at(nSel);
Mat mat = imread(nombre de archivo);
CComboBoxUI* pComboboxUI = static_cast
int nMethod = pComboboxUI->GetCurSel();//Obtener el método de corrección, longitud, doble precisión, latitud y longitud, cilindro , etc. p>
m_fc.Init(mat.cols, mat.rows, CalibrationType(nMethod));
m_fc.org_mat = mat.clone();
float time = m_fc.Calibration();//Comienza a corregir la imagen de ojo de pez
CLabelUI *pLabelUI = static_cast CDuiString strTmp; strTmp.Format(_T("Tiempo de corrección de imagen: %f segundos"), tiempo); pLabelUI->SetText(strTmp); RECT r; ::GetWindowRect(m_hwndImageCalibration, &r); ::InvalidateRect(m_hwndImageCalibration,&r,true);//Redibujar } La función de redibujado está en la clase de corrección de ojo de pez, función m_fc DrawriginImage void FisheyeCalibration::DrawriginImage(HWND hwnd) { if (fix_mat.data) { WinShowMatImage(fix_mat, hwnd); } } void FisheyeCalibration::WinShowMatImage(const cv::Mat& amp; img, HWND hwnd) { if (!::IsWindow(hwnd)) return; HDC hdc = ::GetWindowDC(hwnd) ; RECT rect; GetWindowRect(hwnd, &rect); RECT destRect; destRect.left = 0; arriba = 0; destRect.right = rect.right - rect.left; destRect.bottom = rect.bottom - rect.top; / /Juzgar largo y ancho if ( img.cols<(rect.right - rect.left) && img.rows<(rect.bottom - rect.top)) { int tmp1 = ((rect.right - rect.left) - img.cols) / 2; int tmp2 = ((rect.bottom - rect.top) - img .rows) / 2; destRect.left = tmp1; destRect.right = tmp1 + img.cols; destRect.top = tmp2; destRect.bottom = tmp2 + img. filas; } else { if (rect.bottom == rect.top) return; relación de flotación1 = (float)(rect.right - rect.left) / (float)(rect.bottom - rect.top); relación de float2 = (float)img.cols / ( float)img.rows; if (ratio1 > ratio2) { int w = ratio2*(rect.bottom - rect.top); int h = rect.bottom - rect.top;// ratio2*img.rows; destRect.left = (rect.right - rect.left - w) / 2; destRect.right = (rect.right - rect.left - w) / 2 + w; destRect.top = 0; destRect.bottom = h; } else { int w = rect.right - rect.left;// ratio1*img.cols; int h = ( rect.right - rect.left) / ratio2;// ratio1*img.rows; destRect.left = 0; destRect.right = w; destRect.top = ( rect.abajo-rect.arriba-h ) / 2; destRect.bottom = (rect.bottom - rect.top - h) / 2 + h; } } CvMat _img = img; const CvArr* arr = &_img; CvMat stub; CvMat* imagen = cvGetMat(arr, &stub); //Construir el encabezado BITMAPINFO TAMAÑO tamaño = { imagen->ancho, imagen->alto }; int canales = 3; BITMAPINFO binfo ; memset(&binfo, 0, sizeof(binfo)); BITMAPINFOHEADER& bmih = binfo.bmiHeader; bmih.biSize = tamaño de(BITMAPINFOHEADER); bmih.biWidth = talla.cx; bmih.biHeight = abs(talla.cy); bmih.biPlanes = 1; bmih.biBitCount = (corto sin firmar)(canales * 8); bmih.biCompression = BI_RGB; void* dst_ptr = 0; HBITMAP hb = CreateDIBSection(hdc, &binfo, DIB_RGB_COLORS, &dst_ptr, 0, 0); HDC windowdc = ::CreateCompatibleDC(hdc); SelectObject(windowdc, hb); CvMat dst; cvInitMatHeader(&dst, size.cy, size.cx, CV_8UC3, dst_ptr, (size.cx*canales + 3)&-4); p> int origen = ((IplImage*)arr)->origen; cvConvertImage(imagen, &dst, 1/*origen == 0 ? CV_CVTIMG_FLIP : 0*/); // Mostrar SetStretchBltMode(hdc, COLORONCOLOR); StretchBlt(hdc, destRect.left+1, destRect.top+1, destRect.right - destRect. izquierda, destRect .bottom - destRect.top, windowdc, 0, 0, size.cx, size.cy, SRCCOPY); }