Tutorials for Cv::namedwindow, Glfwwindow, and other programs embedded in MFC

Source: Internet
Author: User

Tutorials for Cv::namedwindow, Glfwwindow, and other programs embedded in MFC

Although MFC is very old, not beautiful, not cross-platform, but in the Windows system, the use of MFC work to verify the interface, or quickly very convenient. Because it is old, there are many solutions available, because it is a library of interfaces provided by MS, so it is easy to implement on windows and is tightly integrated with Windows systems. For example, window messages, etc., in MFC is very convenient to implement. Based on the above reasons, using MFC as a functional verification of a "shell" is a good tool.

Of course, there are many engineering problems that inevitably arise. For example, using glfwCreateWindow the created window, how to embed it in MFC. And often use OPENCV friends, the use of cv::namedWindow functions, the creation of the image/Video display window is also pop-up, how to embed it in MFC somewhere. Well, sometimes you want to create a multi-process program, Allow the created process to be embedded in MFC and run.

1. Preparatory work

All of the following examples, I have integrated into a VS13 solution, download link:

GLFW source I also compiled into VS13 version, after decompression can be opened directly using VS13, download link:

If the points are not enough friends, can give me a message, leave the mailbox or QQ, I can directly send you. Or, you can follow the following, step-by-step is also possible. The second download does not require integration.

First of all, you have to have GLFW source, OpenCV Library, and a visual Studio (I'm using VS2013). Also, in VS13, MFC has discarded multibyte character sets, and if you want to use multibyte character sets in MFC engineering, you need to download a multi-byte character set support package. Download OK, install it.

Then, create a Dialog based MFC project, create a good function, edit the interface, simply add a control on the line, I added a picture control, in the Toolbox, drag in the size of the box. Add a button response function to the < Start > button. Double-click < Start > button. The interface diagram is as follows:




Finally, configure the OPENCV related include directory and library directory and dependencies in the project.

2. OPENCV Window Embedded MFC

I am interested in sharing the question of friends, should not have a problem with OPENCV configuration. If there is a problem, search, csdn above also have a lot of people on the related issues are described in detail.

In the < start > key response function that you added earlier, add the following code.

#include <opencv2\opencv.hpp>voidCaboutmfcdlg::onbnclickedbutton1 () {//TODO: Add control notification handler code hereCRect rect;//idc_static is the ID of the picture control that has just been added to the interfaceGetDlgItem (idc_static)->getwindowrect (&rect);//Create CV window and reset window sizeCv::namedwindow ("View", Cv::window_normal); Cv::resizewindow ("View", Rect. Width (), Rect. Height ());//Set dependency relationship, embed CV window into MFC the main is the following code to work.HWND hwnd = (HWND) Cvgetwindowhandle ("View");    hwnd Hparent =:: GetParent (HWND);    :: SetParent (HWnd, GetDlgItem (idc_static)->m_hwnd); :: ShowWindow (Hparent, sw_hide);//Loop through the pictures in the folder and display. Only as a function verification.Cv::mat img;intindex =0;Charfilename[ -] = {0}; while(true) {sprintf_s (filename,".. \\DragonBaby\\0%03d.jpg ", ++index); img = cv::imread (filename);if((Img.cols <=0) || (Img.rows <=0)) { Break; } cv::imshow ("View", IMG); Cv::waitkey ( -); } CV::d Estroywindow ("View");}

The real key code is six lines, and the others are some dispensable code. Of course, this is just a simple example. When you want to use OPENCV, you must not just cycle through the pictures. However, the above example can give us an inspiration, that is, the OPENCV process and interface can be completely separated from each other, the two do not have too much influence. MFC is only used as a "shell" to show it. Therefore, the above code can be refined again.

Under the solution, create a command-line project. The OPENCV is configured well. Because we are going to use command-line arguments for parameter passing, we need to change the project to use multibyte character sets. How to change: Right-click the project name –> property –> Configuration Properties –> General –> character set, select Use Multibyte character set.

OK, let's start with the code, and organize the following:
First, or change the key response function in MFC, modify the following:

Process_information Pi;voidCaboutmfcdlg::onbnclickedbutton1 () {//TODO: Add control notification handler code hereStartupinfo Startupinfo;memset(&startupinfo,' + ',sizeof(Startupinfo)); STARTUPINFO.CB =sizeof(STARTUPINFO);//Set the process to not display the window when it is created    //startupinfo.dwflags = Startf_useshowwindow;/*startf_useposition*/    //Startupinfo.wshowwindow = Sw_hide;    Char* CommandLine =New Char[ -];memset(CommandLine,' + ', -);//main process window handleHWND Mainwnd = AfxGetMainWnd ()->m_hwnd;//Display control handleHWND Viewwnd = GetDlgItem (idc_static)->m_hwnd;    CRect rect; GetDlgItem (idc_static)->getwindowrect (&rect);//write parameters to the command line and pass to the process to be created immediately    sprintf(CommandLine,"%d %d%d%d", Mainwnd, Viewwnd, rect. Width (), Rect.    Height ()); BOOL B = CreateProcess (".. \\Debug\\OpenCVProc.exe ", CommandLine, NULL, NULL, FALSE, NULL, NULL, NULL, &startupinfo, &AMP;PI);if(!B) MessageBox ("The creation process failed!");

Then, in the newly created command-line project, add the following code:

#include <opencv2\opencv.hpp>#include <Windows.h>int_tmain (intARGC, _tchar* argv[]) {intwidth =0;intHeight =0;    HWND Mainwnd = NULL; HWND Viewwnd = NULL;Char* CommandLine = GetCommandLine ();//Get parameters passed from the main process from the command line    sscanf(CommandLine,"%d %d%d%d", &mainwnd, &viewwnd, &width, &height);//Create CV window and reset window sizeCv::namedwindow ("View", Cv::window_normal); Cv::resizewindow ("View", width, height);//Set dependency relationship, embed CV window into MFC the main is the following code to work.HWND hwnd = (HWND) Cvgetwindowhandle ("View");    hwnd Hparent =:: GetParent (HWND);    :: SetParent (HWnd, Viewwnd); :: ShowWindow (Hparent, sw_hide);//Loop through the pictures in the folder and display. Only as a function verification.Cv::mat img;intindex =0;Charfilename[ -] = {0}; while(true) {sprintf_s (filename,".. \\DragonBaby\\0%03d.jpg ", ++index); img = cv::imread (filename);if((Img.cols <=0) || (Img.rows <=0)) { Break; } cv::imshow ("View", IMG); Cv::waitkey ( -); } CV::d Estroywindow ("View");return 0;}

Compile separately, then run the MFC program, click Start, the effect is as follows:

The debug information output of the command line is essential as a debugging time. So the ugly black box is the first to endure it. To the final stage, the black box can open the comments in two lines of commented-out code in the key response function so that the unsightly black box no longer bounces . The final result is as follows:




Three points in the code that need to be explained, First, when the command-line argument is passed, the window handle HWNDis as intTo pass on. See the MSDN section for instructions on how to know, in Win32, HWNDis an ID of 32 bits. So you can use "%d"Format for transmission. Second, in the key response function of MFC, there is a variable PROCESS_INFORMATION piis placed outside the function body as a global variable. The reason is that after creating a new process, it inevitably involves communication problems, the simplest way is the window message. This variable enables message delivery. Use PostThreadMessage(pi.dwThreadId, WM_TEST, wParam, lParam)The function passes the message to the new process, where WM_TESTis a custom message. finally, in the command-line process, the first parameter of the command line is the window handle of the MFC process, which can be used to send messages to the MFC process. Use SendMessage(mainWnd, WM_TEST, wParam, lParam)Function.

3. Glfwwindow Embedded MFC3.1 configuration GLFW

Previously in a small project, the use of TI provided by the dlp-alc-lightcrafter-sdk-2.0 (referred to as DLP), the SDK provides the source code, through the structure of the light projector + Point grey camera scanning, to get points cloud, and then three-dimensional reconstruction. Need to create an interface for presentation. In the DLP, the point cloud display is to be GLFWwindow encapsulated for display. The function used to create the window in the source code is glfwCreateWindow(width, height, title.c_str(), NULL, NULL) that the above method does not get the desired effect. So I'm glad that Google has a better solution. Thank the Blogger, Successful completion of the expected functionality.

Because of the complexity of my original project, it is not conducive to the direct presentation of the problem solved. So here's what we need to do in a step-by-step. Download the GLFW source in the previous link and download it on GitHub. In addition, you need to download cmake and assume that your PC has installed vs.

Download down the GLFW source folder as shown:




After downloading the good cmake, install. A shortcut to CMake (Cmake-gui) can be found in the Start menu. Open CMake as shown in:



After "where is the source code:" Select the GLFW path you downloaded, as I have shown, my path is E:/glfw/glfw-masterIn E:/glfwCreate a new folder under the directory named glfw-build, fill in the folder path "Where to build the binaries:", and then tap . The following Selection window will appear, select (Of course, my Computer installs the VS13, so select the entry, you correspond to choose your installed VS is good). And then select . Then, you will BUILD_SHARED_LIBSTick on, click again :



and then tap , you will be prompted to generating done. When you are done, open E:/glfw/glfw-buildAfter you will see the following screen, skilled double-click GLFW.slnYou can use vs to open the project. When vs opens, it's refreshing to press F7. VS has started to work. In E:\glfw\glfw-build\src\DebugPath, you will see some of the generated files. are very familiar with things. lib files and DLL files. The VS figure is shown below, and the simple example is found by following the options in the diagram:



Follow, find simple, right-click the pop-up drop-down menu, select < commissioning >–> < Start a new instance >. will be shown a demo effect. Maybe you'll get a bug that hints at E:/glfw/glfw-huild/src/DebugWhat you see inside. glfw3.dllThe file could not be found. The workaround is simple, copy the file to C:\Windows\System32, or to E:/glfw/glfw-huild/src/DebugDirectory JOIN environment variable PathThe first approach seems to need to be restarted.


3.2 Modifying the Code

In simple project, provide the source code, open SIMPLE.C can see its implementation. The following code can be found:

20);window = glfwCreateWindow(640480"Simple example", NULL, NULL);if (!window){    glfwTerminate();    exit(EXIT_FAILURE);}

Where a window is created is the use of glfwCreateWindow a function. In VS, find the glfwCreateWindow definition position of the function, in the glfw3.h file, add a new function glfwCreateWindowEx declaration, as follows:




In the original glfwCreateWindowThe parameter list of the function is newly added. int hParent. The newly added parameters, which should have been HWNDType, but the type is defined in Windows.h, with as few code changes as possible to intInstead of HWNDType, as described in Section two.

Now open the win32_platform.h file, find struct _GLFWwindowWin32 the location where the definition is, new join, and the handle to HWND handleParent save the parent window is passed as a parameter to the function that created the window. As shown in:




Once the parameter structure has been modified, it is now positioned glfwCreateWindowDefinition of a function, defined in a file window.cIn. Replication glfwCreateWindowThe definition of the function, pasted in glfwCreateWindowBelow the definition of the function, change the function name to glfwCreateWindowExand add parameters int hParent. Found in the implementation of the function _glfwPlatformCreateWindowWhere the function is called, add the following code in front of it:

window->win32.handleParent = hParent;

The effect is as follows:




Now, along _glfwPlatformCreateWindowfunction calls to functions always find API CreateWindowExWThe calling place of the function, located at win32_window.cof the file definition static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)is called in the function. In CreateWindowExWAdd the following code before the function and CreateWindowExWThe fourth parameter of the function is changed to window->win32.handleParent.

if (NULL != window->win32.handleParent) {    0;    0);}

As follows:




After the modifications are made, compile the code or run the simple sample to verify. You can still get the effect shown in the previous original code. It shows that the modification of our code does not damage the original performance.

3.3 Effect Verification

Originally, envisioned as the previous example, in the MFC key response function by CreateProcess invoking the compiled Simple.exe executable program, the completion of the interface display. But it has never been successful. CreateProcess the invocation of any example in the sample folder cannot be successful. has not been found specifically why. Because this step is just a validation feature. So it's another way to do the validation.

First, add three edit Control to the original MFC interface, rewrite < start > key response function, the code is as follows:

void CaboutMFCDlg::OnBnClickedButton1(){    // TODO:  在此添加控件通知处理程序代码    HWND viewWnd = GetDlgItem(IDC_STATIC)->m_hWnd;    CRect rect;    GetDlgItem(IDC_STATIC)->GetWindowRect(&rect);    CString str;    str.Format("%d", viewWnd);    GetDlgItem(IDC_EDIT1)->SetWindowText(str);    str.Format("%d", rect.Width());    GetDlgItem(IDC_EDIT2)->SetWindowText(str);    str.Format("%d", rect.Height());    GetDlgItem(IDC_EDIT3)->SetWindowText(str);}

Click < Start >to get the HWND used to display the picture control, as well as the length-width. Displayed in three edit control respectively. Then in simple code to write dead code to complete the function (the brother is incompetent, currently only in such a helpless way to complete functional verification). The code snippet in simple.c is truncated as follows:

Glfwwindowhint (Glfw_context_version_major,2); Glfwwindowhint (Glfw_context_version_minor,0);//Replace the three values obtained in MFC with these three variables, respectively.intViewwnd =5114720;//HWND of picture controlintwidth =536;//width of picture controlintHeight =294;//Picture control's highwindow = Glfwcreatewindowex (width, height,"simple Example", NULL, NULL, VIEWWND);//Comment out the function called by the original creation window, in exchange for our new Create window function Glfwcreatewindowex//window = Glfwcreatewindow (640, 480, "simple example", NULL, NULL);if(!window) {glfwterminate ();Exit(exit_failure);}

Compile the simple project to generate the executable file, and then run simple as shown above. You can see the following results.



4. Other programs embedded in MFC

The topic, but also inadvertently on the site to browse the relevant information, it feels very interesting, try to do a bit, now also put together and share with you. The original author describes some of them in his blog, but is not specific enough. I'll describe it in more detail here. In addition, in the original author's description of the implementation, mainly considering that all functions are implemented at one end, the called EXE is completely unaware that it is embedded in MFC in the run.

The main idea is that, CreateProcess after a call, you can get information about the process that was created, including the process ID. You can then get the window handle of the created process by enumerating the process ID. You can then do the above for the window of the process SetParent . In the sample code, I am calling directly from Windows to bring the Notepad to the demo.

For ease of presentation, use global variables directly here. Two variables are defined to hold the process handle and the process window handle, respectively. Defined as follows:

HWND apphwnd;HANDLE handle;

Then, define the function that created the process, and after the successful creation, take the window handle with the process ID enumeration, with the following code:

//callback function, enumeration get window handleintCALLBACK Enumwindowsproc (HWND hwnd, LPARAM param) {DWORD pID; DWORD TpID = GetWindowThreadProcessId (hwnd, &AMP;PID);if(TpID = = (DWORD) param) {Apphwnd = hwnd;return false; }return true;}The first parameter is the path to the called process, and the second parameter is the list of arguments to be passed inHANDLE startnewprocess (LPCTSTR program, LPCTSTR args) {HANDLE hprocess = NULL;    Process_information ProcessInfo;    Startupinfo Startupinfo; :: ZeroMemory (&startupinfo,sizeof(Startupinfo)); STARTUPINFO.CB =sizeof(STARTUPINFO);    Startupinfo.dwflags = Startf_useshowwindow; Startupinfo.wshowwindow = Sw_hide;if(:: CreateProcess (Program, (LPTSTR) args, NULL,//Process SecurityNull//Thread securityFALSE,//No inheritance        0,//No startup flagsNull//No special environmentNull//Default startup directory&startupinfo, &processinfo)) {/ * Success * /Sleep ( -);//wait for the window of EXE application created:: EnumWindows (&enumwindowsproc, Processinfo.dwthreadid);    hprocess = processinfo.hprocess; }/ * Success * /    returnhprocess;//return HANDLE of process.}

Of course, the shutdown of the process also requires defining the relevant functions.

BOOL CloseProcess() {    return0);}

Now, we re-write the < start > key response function again, the code is as follows:

void CaboutMFCDlg::OnBnClickedButton1(){    // TODO:  在此添加控件通知处理程序代码    handle = StartNewProcess("C:\\Windows\\notepad.exe", NULL);    // CRect rect;    // GetDlgItem(IDC_STATIC)->GetWindowRect(&rect);    // ::MoveWindow(apphwnd, rect.left, rect.top, rect.Width(), rect.Height(), false);    ::SetWindowLong(apphwnd, GWL_STYLE, WS_VISIBLE);    HWND viewWnd = GetDlgItem(IDC_STATIC)->GetSafeHwnd();    ::SetParent(apphwnd, viewWnd);}

The code was simple and I didn't write a comment. The three lines of code that were commented out should have been done to move the newly created process to the specified location, but after the move, an error occurred. No reason was found. Let me know if you want a friend who knows the reason and has successfully solved it. Thank you.

This content is almost the same as the example given above for the original author. Interested friends, you can view the original author's statement.

Finally, the resulting example is as follows:



OK, finish the call.

Tutorials for Cv::namedwindow, Glfwwindow, and other programs embedded in MFC

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.