Learn the MFC process by writing the Serial Port Helper Tool--(eight) some problems encountered

Source: Internet
Author: User
Tags function prototype stdin

learn the MFC process by writing a Serial port helper tool

Because it has been done several times MFC programming, each time the project is completed, MFC basic operation is clear, but too long time no longer contact with MFC project, again do MFC project, but also from the beginning familiar. This time by doing a serial assistant once again familiar with MFC, and made a record, in order to facilitate later access. The process of doing more is encountered problems directly Baidu and Google search, so many are superficial understanding, know it does not know why. In addition to do this tool just to get familiar with, many features are not perfect! (development tool VS2008)

(eight) Some of the problems encountered

The controls used in this example are covered, and this section is a few of the problems encountered in this example

1. resolves an unresolved external symbol using enumerating serial-port classes

Recently in the development of a serial communication program, using the class provided by Zach Gorman. However, under VS2005, the following conditions will appear:
1>------Started Build: Project: Communication, Configuration: Debug Win32------
1> is compiling ...
1>enumserial.cpp
1> is linking ...
1>enumserial.obj:error LNK2019: unresolved external symbols[email protected], the symbol in the function[email protected]@[email protected]@@[email protected]Referenced in @@@z$0
1>enumserial.obj:error LNK2019: unresolved external symbols[email protected], the symbol is in the function "void __cdecl ENUMPORTSWDM (class carray<struct sserinfo,struct sserinfo &> &)" ([email protected]@[email protected]@@[email protected]@@@z) is referenced in
1>enumserial.obj:error LNK2019: unresolved external symbols[email protected], the symbol is in the function "void __cdecl ENUMPORTSWDM (class carray<struct sserinfo,struct sserinfo &> &)" ([email protected]@[email protected]@@[email protected]@@@z) is referenced in
1>enumserial.obj:error LNK2019: unresolved external symbols[email protected], the symbol is in the function "void __cdecl ENUMPORTSWDM (class carray<struct sserinfo,struct sserinfo &> &)" ([email protected]@[email protected]@@[email protected]@@@z) is referenced in
1>enumserial.obj:error LNK2019: unresolved external symbols[email protected], the symbol is in the function "void __cdecl ENUMPORTSWDM (class carray<struct sserinfo,struct sserinfo &> &)" ([email protected]@[email protected]@@[email protected]@@@z) is referenced in
1>c:\documents and settings\administrator\ Desktop \dev\modbus Communication protocol Demo-09-20\debug\communication.exe:fatal error Lnk1120:5 an unresolved external command
1> build logs are saved in the file://c:\documents and settings\administrator\ Desktop \dev\modbus Communication protocol demo-09-20\communication\debug\ BuildLog.htm "
1>communication-6 a bug, 0 warnings
========== generated: 0 succeeded, 1 failed, 0 latest, 0 skipped ==========

This is because VS2005 does not give us the import of setupapi.dll files, there are two workarounds:
1: Insert #pragma comment (lib, "SetupAPI") at the beginning of your. h file
2: Or press Set

Reference:http://blog.csdn.net/l_peter/article/details/7599122

2. MFC Add dialog box error: enum {IDD = xxx}; " XXX ": undeclared identifier

XXX is the ID of the Add dialog box, and the Code in the dialog box corresponds to class xxx.h file dialog class declaration when there is code enum {IDD = xxx};

Solution Add # include "Resource.h" in the Xxx.h file

3. how MFC programs use printf to output debugging information

Imagine that we wrote a library in the command line under the Win32 console, the diagram is easy to debug directly with printf output log, but later the integration of the library using MFC and other forms of the program, so the original with printf output log information can not be seen, but we need to see this Some log information, or even preferably output to a file to facilitate analysis, how to deal with it?

First, we consider outputting the log information to the console and follow the steps below.

1, add header file

1

2

#include <io.h>

#include <fcntl.h>

2, add the following function to the file that will be called

1

2

3

4

5

6

7

8

void Initconsolewindow ()

{

AllocConsole ();

HANDLE HANDLE = GetStdHandle (Std_output_handle);

int hcrt = _open_osfhandle ((long) handle,_o_text);

FILE * HF = _fdopen (HCRT, "w");

*stdout = *HF;

}

3, add a call to create the console in the initialization function

1

2

3

4

5

6

7

8

9

10

BOOL Chellomfcdlg::oninitdialog ()

{

CDialog::OnInitDialog ();

Initconsolewindow (); Add

printf ("str =%s

"," Debug output goes to Terminal

");

......

}

Call this function will pop up a console,printf information will appear on this, we can view the log information. However, if the log information output is too large, the Console can not display all the information, then we would like to use printf to the log output to a fixed file, which will be used for the output redirection.

As we all know, in the Windows terminal input "dir" will be listed in the current directory file list, enter "dir > 1.txt" can be the current directory file list exported to "1.txt", Linux terminal also has similar command "ls > 1.txt". Here is the output redirect, we can use the same idea through the freopen to achieve the log information file output.

Include the header file first, and then one sentence to achieve the output redirection

1

2

3

4

#include <stdio.h>

#include <stdlib.h>

Freopen ("Log.txt", "w", stdout); REDIRECT stdout to Log.txt

Return to normal stdout output

1

2

Freopen ("CON", "w", stdout); Recover stdout (Windows)

Freopen ("/dev/console", "w", stdout); Recover stdout (Linux)

You can also use this

1

2

3

4

5

FILE *outbak = stdout;

stdout = fopen ("Log.txt", "w");

......

Fclose (stdout);

stdout = Outbak;

In fact, StdIn also has a similar redirect operation:

1

2

3

Freopen ("Info.txt", "R", stdin); REDIRECT stdin to Info.txt

Freopen ("CON", "R", stdin); Recover (Windows)

Freopen ("/dev/console", "R", stdin); Recover (Linux)

The method above is to avoid a lot of repetitive work by adjusting printf as the code has been written out. Of course, the best way to avoid all this is to define a log output macro when you first write the code, and follow this macro to adjust the log output.

Original http://xuhehuan.com/2297.html

4. ways to resolve header files that contain problems with each other

The so-called advance reference refers to a type that is used to define variables and declare functions before they are defined.
In general, C + + requires that all types must be defined before use, but in some special cases this requirement is not met, for example, a non-modal dialog object pointer is reserved in class CMyView that is used to display/modify some information. In order to implement the dialog "apply" button, make changes to the dialog box immediately updated to the view interface, for this reason, you need to save the view class pointer in the dialog box class, so that the definition of the relationship becomes the following code:
#ifndef __myview_h__
#define __myview_h__
This is the head function of the view class.
#include "MyDialog.h"
Class CMyView::p ublic CView
{
Protected
CMyDialog * PDLG;
Here are other definitions
};
#endif
#ifndef __mydialog_h__
#define __mydialog_h__
This is the definition of the dialog box class
#include "MyView.h"
Class CMyDialog::p ublic CDialog
{
Protected
CMyView * PView;
Other definitions
};
#endif
From the compiler's point of view, when compiling MyDialog.CPP, the system first defines the macro __mydialog_h__ and then contains the # include "MyDialog.h" in Myview.h,myview.h because __mydialog_h__ is already defined, So it doesn't work anymore. In the declaration of the CMyView class, cmydialog* Pdlg will cause the compiler to produce an error such as "CMyDialog" type, which can be similar to the error in compiling the MyView.CPP file.
More generally, Class A and Class B need to refer to each other so that there must be a class that is defined first, and then the other class is defined so that the class that is defined after the class referenced by the preceding definition leads to the so-called advance reference.
There are several ways to deal with errors that lead to advance references:
1) using the class declaration
Before referencing a class ahead of time, a special statement is first used to indicate that the identifier is a class name and is about to be referenced in advance. It is used in the following ways:
A) Use class ClassB; Declare the class name that will be referenced in advance
b) Define class ClassA
c) Define class ClassB;
d) Compile the implementation code for two classes.
The above method applies to all code in the same file, in general, ClassA and CLASSB have their own header files and CPP files, this
The method needs to evolve into:
A) define ClassA and CLASSB separately and implement them in the CPP file.
b) Use class ClassB at the beginning of the two header files, and class ClassA;
c) A header file containing another class in two CPP files
Note: This method remembers that you cannot use the class name to define variable parameters for variables and functions, only to define references or pointers.
2) Use global variables
Because global variables can avoid the advance reference, do not repeat. My habit is to add the extern statement of the class object to the end of the class header file, and everyone likes
How to write that is not a big problem, the key is to ensure that the header file is not included in the random.
3) Use the base class pointer.
This method uses the base class pointer wherever the reference class is quoted. In general, two mutually referenced classes do not involve their base classes and therefore do not cause
Advance reference. In the beginning of the example said: In the CMyDialog class with cview* instead of cmyview*, in the CMyView class with cdialog* instead of cmydialog*, so inevitably
does not lead to advance references.
Note: In this article, for the sake of convenience, the class AClass, the statement becomes the declaration of the classes AClass, the class AClass start to AClass classes member variables,
The description of the member function prototype is called the definition of the class, and the part in the CPP is called the definition of the class. If you have a different understanding of these three words, please follow your own intentions.

Translate these three words into corresponding words to understand.

*************************************************************************************************************** **********************************

First, the class nesting question
C + + header file Duplication is really a headache, and some time ago when you were doing a simple data structure demo program, you encountered this problem more than once. Suppose we have two classes A and B, respectively defined in the respective file A.h and B.h, but in a to use the b,b also use a, but this is of course wrong:

CPP Code

1. class B;

2. class A

3. {

4. Public:

5. b b;

6.};

7.

8. Class B

9. {

Public:

A. A;

12.};

Because in a object to open a piece of space belonging to B, and B has a space, is a logic error, can not be achieved. In this case, we just need to change the B-type member in the Class A to the pointer form to avoid this infinite extension. Why would you want to change a instead of B? Because even if you do a similar action in B, you will still compile the error, on the surface this is only a sequential problem.
Why is that? Because the C + + compiler compiles the source files from top to bottom, the definition of each data always needs to know the size of the type of data defined. After declaring the statement Class B, the compiler already knows that B is a class, but the data in it is unknown, so the size of type B is not known. This causes the compilation to fail, and the following compilation error will be vc++6.0:

Vc output Code

1. Error C2079: ' B ' uses undefined class ' B '

After changing B in a to the B pointer type, the pointer occupies a certain amount of space on a particular platform (4 bytes on the Win32 platform), which can be compiled.

Ii. nesting of classes in different header files
In actual programming, different classes are generally placed in separate header files, so that two classes will have a different problem when referencing each other. Repeating compilation is the root cause of the problem. To ensure that header files are compiled only once, the common approach in C + + is to use conditional compilation commands. In the header file we often see the following segment of the statement (in the case of vc++6.0 auto-generated header files):

CPP Code

1. #if!defined (afx_stack_h__1f725f28_af9e_4beb_8560_67813900ae6b__included_)

2.

3. #define Afx_stack_h__1f725f28_af9e_4beb_8560_67813900ae6b__included_

4.

5.//Many statements ...

6.

7. #endif

One of the first sentence # if!defined also often do #ifndef, the same effect. This means that if the macro is not defined, then it is defined and then all statements are executed until #endif. If the next time you want this code, the duplicated code will not be executed again because the macro has already been defined. This is really a clever and efficient way. In the high version of VC + +, you can also use this command to replace all of the above:

CPP Code

1. #pragma once

It means that the code in this file is only used once.

But do not assume that the use of this mechanism is all done, such as in the following code:

CPP Code

1.//code in file A.h

2. #pragma once

3. #include "B.h"

4. class A

5. {

6. Public:

7. b* B;

8.};

9.

10.//code in file B.h

One. #pragma once

#include "A.h"

class B

14. {

Public:

* A;

17.};

Here both use pointer members, so nesting itself is not a problem, after using the # include "A.h" in front of the main function, the main compilation error is as follows:

Error C2501: ' A ': missing Storage-class or type specifiers

Vc output Code

1. Error C2501: ' A ': missing Storage-class or type specifiers

Still the type cannot find the error. In fact, there is still a need for a predecessor statement. After you add the predecessor declaration separately, you can compile it successfully. The code form is as follows:

CPP Code

1.//code in file A.h

2. #pragma once

3. #include "B.h"

4. class B;

5.

6. class A

7. {

8. Public:

9. b* B;

10.};

11.

12.//code in file B.h

#pragma once

#include "A.h"

class B;

16.

. class B

18. {

. Public :

* A;

21.};

This can at least indicate that the header file contains no substitute for the predecessor declaration. Sometimes you only have to rely on a predecessor statement to solve the problem. We also have to think about, is it necessary to have the header file included in the preceding statement? We tried to get rid of the # include lines in A.h and B.h and found that no new errors occurred. So when do you need a front-end statement, when do you need a header file to contain it?
Three, two points principle
The header file contains actually a thought very cumbersome work, not only we look tired, compiler compile time is also very tired, plus the header file often appear in the macro definition. It feels like the expansion of a variety of macro definitions is time-consuming and far less fast than a custom function. Here, only the different header files, the source file of the sentence structure of the problem of two points, for reference only:
The first principle should be, if you can not include a header file, then do not include. This is where the predecessor declaration resolves the issue. If you are using just a pointer to a class, do not use the object of the class (non-pointer), and do not have access to the specific members of the class, then the pre-declaration is ready. Because the size of the data type of the pointer is specific, the compiler can be informed.
The second principle should be to include the header file in the CPP file as much as possible, rather than in the header file. Assuming that a member of Class A is a pointer to Class B, using the predecessor Declaration of Class B in the header file of Class A and compiling it successfully, we need to access the specific members of B in the implementation of a, so we need to include the header file. Then we should include the header file of Class B rather than the declaration part (H file) in the implementation part of Class A (CPP file).

Citation:http://blog.csdn.net/yang_lang/article/details/6767439

5. Modify the AfxMessageBox dialog box title

The AfxMessageBox dialog box title defaults to the project name, and the dialog box is intended to give the user information, and the user-oriented software name is usually different from the project name, for example, the software may be in Chinese name. So, sometimes we need to make AfxMessageBox popup dialog with the title of the current software name.

Workaround: Locate the string table in the resource view and open it, and modify the title of ID Afx_ids_app_title to the value you want.

Attention:

When you open the string table and do not see the Afx_ids_app_title item, you need to add this item manually.

1 Right-click New string:

2 Double-click the new string ID and change to Afx_ids_app_title:

Citation: http://blog.csdn.net/dezhihuang/article/details/52085774

6. How to open the serial port of COM10 and above in VC

Today with a previous serial port program, found that the serial port can not open. Because the serial port is not the usual COM1, COM2 but larger than the COM10 port, thinking is very simple to add a few options can be easily done, the results plus after testing, found always failed to initialize, debug found in the CreateFile always fail, find MSDN A look sure there is a difference here.

Win32 API function CreateFile () In addition to open ordinary files, you can also open the device, such as can be used to open the serial port, to obtain a serial handle. When you use the CreateFile () function to open the serial port, the file sharing mode should be set to 0 (for exclusive), the creation parameter is set to Open_existing, and the template must be set to NULL.

If COM1 to COM9, the function can be returned successfully using "COM1"-"COM9" as the file name passed to the CreateFile () function. However, if the operand is COM10 and above the port, calling the file name in this way calls the CreateFile () function to return Invalid_handle_value, indicating that the port cannot be opened.

The reason for this strange phenomenon is that Microsoft's pre-defined standard device contains "COM1"-"COM9". Therefore, "COM1"-"COM9" is passed to the function as the file name, and the operating system automatically resolves it to the appropriate device. But for COM10 and above the serial port, "COM10" such as the file name System is regarded as the general meaning of the files, but not the serial device.

In order to increase support for COM10 and above serial ports, Microsoft rules that if you want to access such a device, you should use such a file name (take COM10 as an example): \ \. COM10
Therefore, for COM10 and above the serial port, the CreateFile () call style should be adjusted as follows:

CreateFile ("\\\\.\\COM10",//define serial name fdwaccess,//access mode (read/write) 0,//share mode: Must be set to 0, indicates device exclusive use NULL,//confidentiality

Open_existing,//Must be set to Open_existing

0,//file attribute, if it is asynchronous, can be set to

Null//template, serial device must be set to NULL

);

This way you can also open the COM1~COM9 serial port.

Citation: http://blog.csdn.net/playboy1/article/details/48316263

Learn the MFC process by writing the Serial Port Helper Tool--(eight) some problems encountered

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.