Converting a AfxMessageBox into a CTaskDialog using DoMessageBox - visual-c++

I have written this function so far:
int CMFCApplication3App::DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt)
{
CString strContent = CString(lpszPrompt);
CString strTitle; strTitle.LoadString(AFX_IDS_APP_TITLE);
CTaskDialog dlgTaskMessageBox(strContent, _T(""), strTitle);
int iPixelWidth = (::GetSystemMetrics(SM_CXSCREEN) / 100) * 30;
int iDialogUnitsWidth = MulDiv(iPixelWidth, 4, LOWORD(GetDialogBaseUnits()));
dlgTaskMessageBox.SetDialogWidth(iDialogUnitsWidth);
/*
if (nType & MB_ICONINFORMATION)
dlgTaskMessageBox.SetMainIcon(TD_INFORMATION_ICON);
if (nType & MB_ICONERROR)
dlgTaskMessageBox.SetMainIcon(TD_ERROR_ICON);
if (nType & MB_ICONWARNING)
dlgTaskMessageBox.SetMainIcon(TD_WARNING_ICON);
if (nType & MB_ICONQUESTION)
{
HICON hIcon = LoadIcon(IDI_QUESTION);
dlgTaskMessageBox.SetMainIcon(hIcon);
}
int iButtons = 0;
if (nType & IDYES)
iButtons |= TDCBF_YES_BUTTON;
if (nType & IDNO)
iButtons |= TDCBF_NO_BUTTON;
if (nType & IDCANCEL)
iButtons |= TDCBF_CANCEL_BUTTON;
if (nType & IDOK)
iButtons |= TDCBF_OK_BUTTON;
if (nType & IDRETRY)
iButtons |= TDCBF_RETRY_BUTTON;
dlgTaskMessageBox.SetCommonButtons(iButtons);
*/
if (nType == (MB_YESNOCANCEL | MB_ICONERROR))
{
dlgTaskMessageBox.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
dlgTaskMessageBox.SetMainIcon(TD_ERROR_ICON);
}
if (nType == (MB_YESNOCANCEL | MB_ICONWARNING))
{
dlgTaskMessageBox.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
dlgTaskMessageBox.SetMainIcon(TD_WARNING_ICON);
}
if (nType == (MB_YESNOCANCEL | MB_ICONINFORMATION))
{
dlgTaskMessageBox.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
dlgTaskMessageBox.SetMainIcon(TD_INFORMATION_ICON);
}
/*
if (nType == (MB_YESNOCANCEL | MB_ICONQUESTION))
{
dlgTaskMessageBox.SetCommonButtons(TDCBF_YES_BUTTON | TDCBF_NO_BUTTON | TDCBF_CANCEL_BUTTON);
HICON hIcon = LoadIcon(IDI_QUESTION);
dlgTaskMessageBox.SetMainIcon(hIcon);
}
*/
return dlgTaskMessageBox.DoModal();
}
I have two issues with this and am happy to split as two questions:
Using IDI_QUESTION is causing the application to crash.
Isn't there an easier way to decode nType into the various buttons and icon required?

Using IDI_QUESTION is causing the application to crash
That's because IDI_QUESTION is a standard icon and must be loaded by passing a NULL instance handle to ::LoadIcon, but MFC's CWinApp::LoadIcon passes AfxGetResourceHandle() instead. The following bypasses MFC and calls the Win32 API directly.
HICON hIcon = ::LoadIcon(NULL, IDI_QUESTION);
Isn't there an easier way to decode nType into the various buttons and icon required?
Not a lot easier, but they could be grouped to lessen the duplication.
int nCommonButtons = 0;
switch(nType)
{
case MB_YESNOCANCEL:
nCommonButtons |= TDCBF_CANCEL_BUTTON;
case MB_YESNO:
nCommonButtons |= TDCBF_YES_BUTTON | TDCBF_NO_BUTTON;
break;
case MB_OKCANCELRETRY:
nCommonButtons |= TDCBF_RETRY_BUTTON;
case MB_OKCANCEL:
nCommonButtons |= TDCBF_CANCEL_BUTTON;
case MB_OK:
nCommonButtons |= TDCBF_OK_BUTTON;
break;
//... etc
}

I thought I would add this as addition answer.
Taking onboard the accepted answer (#dxiv) and the comments that were made below (#sergiol):
int CMeetingScheduleAssistantApp::DoMessageBox(LPCTSTR lpszPrompt, UINT nType, UINT nIDPrompt)
{
CString strContent = CString(lpszPrompt);
CString strTitle = CString();
if (!CTaskDialog::IsSupported())
return CWinAppEx::DoMessageBox(lpszPrompt, nType, nIDPrompt);
ENSURE(strTitle.LoadString(AFX_IDS_APP_TITLE));
CTaskDialog dlgTaskMessageBox(strContent, _T(""), strTitle);
int iPixelWidth = (::GetSystemMetrics(SM_CXSCREEN) / 100) * 30;
int iDialogUnitsWidth = MulDiv(iPixelWidth, 4, LOWORD(GetDialogBaseUnits()));
dlgTaskMessageBox.SetDialogWidth(iDialogUnitsWidth);
HICON hQuestionIcon = ::LoadIcon(nullptr, IDI_QUESTION);
// Icon
switch (nType & MB_ICONMASK)
{
case MB_ICONERROR:
dlgTaskMessageBox.SetMainIcon(TD_ERROR_ICON);
break;
case MB_ICONWARNING:
dlgTaskMessageBox.SetMainIcon(TD_WARNING_ICON);
break;
case MB_ICONINFORMATION:
dlgTaskMessageBox.SetMainIcon(TD_INFORMATION_ICON);
break;
case MB_ICONQUESTION:
dlgTaskMessageBox.SetMainIcon(hQuestionIcon);
break;
}
// Buttons
int nCommonButtons = 0;
switch (nType & MB_TYPEMASK)
{
case MB_YESNOCANCEL:
nCommonButtons |= TDCBF_CANCEL_BUTTON;
[[fallthrough]];
case MB_YESNO:
nCommonButtons |= TDCBF_YES_BUTTON | TDCBF_NO_BUTTON;
break;
case MB_RETRYCANCEL:
nCommonButtons |= TDCBF_RETRY_BUTTON | TDCBF_NO_BUTTON;
break;
case MB_OKCANCEL:
nCommonButtons |= TDCBF_CANCEL_BUTTON;
[[fallthrough]];
case MB_OK:
default:
nCommonButtons |= TDCBF_OK_BUTTON;
}
dlgTaskMessageBox.SetCommonButtons(nCommonButtons);
return static_cast<int>(dlgTaskMessageBox.DoModal());
}
I was not aware of these:
MB_ICONMASK
MB_TYPEMASK
The only scenario I have not catered for is MB_ABORTRETRYIGNORE because I do not see common buttons equivalents for Abort and Ignore.

Related

FUSE Filesystem Example

This is in reference to hello_getattr function in hello.c, which comes as example in libfuse.
What does st_mode field signify in the code below? To be specific why are setting st_mode to specific values as shown below?
static int hello_getattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{
(void) fi;
int res = 0;
memset(stbuf, 0, sizeof(struct stat));
if (strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
} else if (strcmp(path+1, options.filename) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = strlen(options.contents);
} else
res = -ENOENT;
return res;
}

my linux C program cannot receive data from Arduino through USB Serial

My Linux C application cannot receive bytes from Arduino
Hi all, I intend to use Arduino Mega 2560 as a programmer for AT89S52 (a family of 8051 microprocessor). The Arduino board connects to PC via USB Serial cable.
At first I need to write a program in my Ubuntu to communicate with Arduino board. My program can open connection and write bytes to Arduino properly (I tested by turning led on/off), but the problem is that the Linux program cannot receive data from Arduino.
I already searched through many tutorials and forums but still cannot resolve the problem, so I post question here and hope that someone can help me.
Below is my functon used to open connection to device
AT89S_EID usbserial_open ( char* dev_name,
UsbSerialDevice* dev_ptr,
int baudrate,
int config ) {
speed_t io_baudrate = B9600;
if (dev_name == NULL || dev_ptr == NULL)
{
return AT89S_EID_ARG_NULL;
}
if (baudrate != US_BAUDRATE_9600
&& baudrate != US_BAUDRATE_19200
&& baudrate != US_BAUDRATE_115200)
{
return AT89S_EID_SERIAL_BAUDRATE_INVALID;
}
if (config != US_CONFIG_8N1
&& config != US_CONFIG_7E1
&& config != US_CONFIG_7O1)
{
return AT89S_EID_SERIAL_CONFIG_INVALID;
}
// store device name
strcpy(dev_ptr->name, dev_name);
// open device
dev_ptr->fd = open (dev_ptr->name,
O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
if (dev_ptr->fd < 0)
{
return AT89S_EID_SERIAL_OPEN;
}
// get current termios settings
if (tcgetattr(dev_ptr->fd, &dev_ptr->tios) < 0)
{
return AT89S_EID_SERIAL_GET_ATTR;
}
// set input/output baudrdate
if (baudrate == US_BAUDRATE_9600)
io_baudrate = B9600;
else if (baudrate == US_BAUDRATE_19200)
io_baudrate = B19200;
else if (baudrate == US_BAUDRATE_115200)
io_baudrate = B115200;
if (cfsetispeed(&dev_ptr->tios, io_baudrate) != 0
|| cfsetospeed(&dev_ptr->tios, io_baudrate) != 0)
{
return AT89S_EID_SERIAL_SET_IOSPEED;
}
// enable receiver, ignore status line
dev_ptr->tios.c_cflag |= (CREAD | CLOCAL);
// set config
if (config == US_CONFIG_8N1)
{
dev_ptr->tios.c_cflag &= ~PARENB;
dev_ptr->tios.c_cflag &= ~CSTOPB;
dev_ptr->tios.c_cflag &= ~CSIZE;
dev_ptr->tios.c_cflag |= CS8;
}
else if (config == US_CONFIG_7E1)
{
dev_ptr->tios.c_cflag |= PARENB;
dev_ptr->tios.c_cflag &= ~PARODD;
dev_ptr->tios.c_cflag &= ~CSTOPB;
dev_ptr->tios.c_cflag &= ~CSIZE;
dev_ptr->tios.c_cflag |= CS7;
}
else if (config == US_CONFIG_7O1)
{
dev_ptr->tios.c_cflag |= PARENB;
dev_ptr->tios.c_cflag |= PARODD;
dev_ptr->tios.c_cflag &= ~CSTOPB;
dev_ptr->tios.c_cflag &= ~CSIZE;
dev_ptr->tios.c_cflag |= CS7;
}
// no HW flow control
dev_ptr->tios.c_cflag &= ~CRTSCTS;
// no input processing (raw input)
dev_ptr->tios.c_iflag &= ~(IXON | IXOFF | IXANY);
// other input settings
dev_ptr->tios.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
// no output processing (raw output)
dev_ptr->tios.c_oflag &= ~OPOST;
// control character settings
dev_ptr->tios.c_cc[VMIN] = 1; // wait for 1 minimum chacacter received
dev_ptr->tios.c_cc[VTIME] = 0; // no timeout when waiting for charater
// commit new settings
if (tcsetattr(dev_ptr->fd, TCSANOW, &dev_ptr->tios) < 0)
{
return AT89S_EID_SERIAL_SET_ATTR;
}
// wait for device reset & sync up
usleep(1500 * 1000);
return AT89S_EID_OK;
} /* usbserial_open */
And this is the receiving function:
AT89S_EID usbserial_recv ( UsbSerialDevice* dev_ptr,
unsigned char* data_ptr,
int data_len ) {
int read_byte = 0;
char b[1];
if (dev_ptr == NULL
|| data_ptr == NULL)
{
return AT89S_EID_ARG_NULL;
}
// block reading
fcntl(dev_ptr->fd, F_SETFL, 0);
// start receiving data
while (read_byte < data_len)
{
if (read(dev_ptr->fd, b, 1) > 0)
{
data_ptr[read_byte++] = *b;
}
else
{
if (errno == EAGAIN)
continue;
else if (errno == ETIMEDOUT)
break;
else
return AT89S_EID_SERIAL_RECV;
}
}
return AT89S_EID_OK;
} /* usbserial_recv */
So sorry for posting a long code :)
I already searched through many tutorials and forums but still cannot resolve the problem. I believe that the Arduino code is working fine because I used some other tools to test it (e.g.: minicom)
I resolved my problem. Just add flush function when open the connection to device, everything can be working fine.
tcflush(fd, TCIOFLUSH);

How to connect a bluetooth input device to a computer?

I have created a bluetooth input device (stylus) and would like to connect it to both a Mac and Windows (and preferably Linux in the future).
Is there an ideal software / language to use to create a cross-platform application? I have considered writing native applications for each, but I don't feel the application will be so complex that this is absolutely necessary.
The application will take the input data of the BT device and use it to move the cursor around the screen and provide click and pressure functionality.
Thank you in advance.
I don't know how you device is set up.
However, if you managed to put on it a PIC (Such as the Arduino ATMega328) with at least one serial interface, you could be able to connect it to your PC via Universal Serial Bus (USB).
After that you will be able to open a pipe to your device in many languages.
C is always a good choice both for Linux and OS X, using POSIX libraries will make it even easier.
This snippet I wrote taking some tips online may help to get started
int init_port (const char * port_name, int baud) {
/* Main vars */
struct termios toptions;
int stream;
/* Port data */
speed_t brate = baud;
if ((stream = apri_porta(port_name)) < 1)
return 0;
if (tcgetattr(stream, &toptions) < 0) {
printf("Error");
return 0;
}
/* INITIALIZING BAUD RATE */
cfsetispeed(&toptions, brate);
cfsetospeed(&toptions, brate);
// IMPORTANT BLOCK OF OPTIONS TO MAKE TX AND RX WORKING
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
toptions.c_cflag &= ~CRTSCTS;
toptions.c_cflag |= CREAD | CLOCAL;
toptions.c_iflag &= ~(IXON | IXOFF | IXANY);
toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
toptions.c_oflag &= ~OPOST;
toptions.c_cc[VMIN] = 0;
toptions.c_cc[VTIME] = 0;
tcsetattr(stream, TCSANOW, &toptions);
if (tcsetattr(stream, TCSAFLUSH, &toptions) < 0) {
printf("Error");
return 0;
}
return stream;
}
int open_port (const char * port_name) {
int stream;
stream = open(port_name, O_RDWR | O_NONBLOCK );
if (stream == -1) {
printf("apri_porta: Impossibile aprire stream verso '%s'\n", port_name);
return -1;
}
return stream;
}
int close_port (int stream) {
return (close(stream));
}
int write_to_port(int stream, char * str) {
int len = (int)strlen(str);
int n = (int)write(stream, str, len);
if (n != len)
return 0;
return 1;
}
int read_from_port(int fd, char * buf, int buf_max, char until) {
int timeout = 5000;
char b[1];
int i=0;
do {
int n = (int)read(fd, b, 1);
if( n==-1) return -1;
if( n==0 ) {
usleep( 1 * 1000 );
timeout--;
continue;
}
buf[i] = b[0];
i++;
} while( b[0] != until && i < buf_max && timeout > 0 );
buf[i] = 0; // null terminate the string
return 0;
}
Objective-C (OS X) has got a good library which works like a charm (ORSSerialPort)
However, if you would like to have a cross-platform solution, Java is the best choice either for Windows, OS X and Linux.
I hope this helped you and others to get started.
Feel free to PM me if you need further help.
Best regards.

Using State Machine for Controlling Data

I am sending some data from one Atmega644P to another Atmega644P consecutively. The first three bytes are SYN(0x16), DLE(0x10), and STX(0x02). On the receiving part, I made a state machine to control if I receive those bytes correctly.
When it is in DLE_1_s state, it goes directly to the "else" statement, although the data is 0x10. Why is this happening?
I am using Peter Fleury's uart library.
This is the diagram I am trying to implement:
Code:
int main(void)
{
DDRD = 0b11111010; // PORTD input/output.
DDRC = 0xFF;
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
sei();
unsigned int rec_char;
char buffer[7];
while(1)
{
rec_char=uart_getc();
switch(state)
{
case SYN_s:
{
if ((unsigned char) rec_char == 0x16) // SYN
{
state=DLE_1_s;
}
else
{
state=SYN_s;
}
}
break;
case DLE_1_s:
{
if ((unsigned char) rec_char == 0x10) // DLE
{
state=STX_s;
}
else if ((unsigned char) rec_char == 0x16) // SYN
{
state=DLE_1_s;
}
else
{
state=SYN_s;
}
}
break;
case STX_s:
{
if ((unsigned char) rec_char == 0x02) // STX
{
state=TARGET_NO_1_s;
}
else if ((unsigned char) rec_char == 0x16) // SYN
{
state=DLE_1_s;
}
else
{
state=SYN_s;
}
}
break;
#include <stdio.h>
#define FAKE 1
#if FAKE
unsigned DDRD, DDRC;
#define UART_BAUD_RATE 123
#define F_CPU 0
#define UART_BAUD_SELECT(a,b) (((a)<<8)+((b)&0xff))
#define UART_NO_DATA 1
#define SYN 0x16
#define DLE 0x10
#define STX 0x02
extern void uart_init(unsigned);
extern void sei(void);
extern void maybe_sleep(void);
extern unsigned uart_getc(void);
#endif
int main(void)
{
DDRD = 0b11111010; // PORTD input/output.
DDRC = 0xFF;
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
sei();
unsigned int rec_char;
int state;
for(state=0; ; ) {
unsigned int hi,lo;
rec_char = uart_getc();
hi = rec_char >> 8;
lo = rec_char & 0xff;
switch (hi) { /** handle errors from uart here */
case 0: break;
case UART_NO_DATA: /* no receive data available */
maybe_sleep();
continue;
default:
fprintf(stderr, "Hi=%x Lo=%x\n", hi, lo);
/* some cleanup here ... */
state =0;
continue;
}
switch(state) {
case 0:
if (lo == SYN) { state = 1 ; break;}
break;
case 1:
if (lo == DLE) { state = 2; break; }
if (lo == SYN) { break; }
state= 0;
break;
case 2:
if (lo == STX) { state = 3; break; }
if (lo == SYN ) { state = 1; break; }
state = 0;
break;
case 3:
/* handle payload here ... */
break;
}
}
return 0;
}

Error while saving a bitmap in MFC

I am displaying an image in my MFC application and I want to save it as bitmap.
Here is my code.
BITMAPFILEHEADER bh;
ZeroMemory(&bh, sizeof(BITMAPFILEHEADER));
bh.bfType = 0x4d42; //bitmap
bh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bh.bfSize = bh.bfOffBits + ((IM_WIDTH*IM_HEIGHT*2)*3);
CFile file;
if(file.Open("Image1.bmp", CFile::modeCreate | CFile::modeWrite))
{
file.Write(&bh, sizeof(BITMAPFILEHEADER));
file.Write(&(bmi.bmiHeader), sizeof(BITMAPINFOHEADER));
file.Write(im_final, 3 * IM_WIDTH * IM_HEIGHT*2);
file.Close();
}
I am using the same BITMAPINFOHEADER which I used to display the image.
But the saved image is not correct.
Please tell me what am I doing wrong.
This is the code I am using now which works fine:
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4d42; /* "BM" */
bmfh.bfSize = (sizeof(BITMAPFILEHEADER) + bmih.biSize + bmih.biClrUsed * sizeof(RGBQUAD) + bmih.biSizeImage);
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + bmih.biSize + bmih.biClrUsed * sizeof(RGBQUAD);
CString file = m_filepath;
char* savefile = file.GetBuffer();
hFile = CreateFile(savefile, GENERIC_WRITE, 0, (LPSECURITY_ATTRIBUTES) NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
WriteFile(hFile, (char *) &bmfh, sizeof(BITMAPFILEHEADER), (LPDWORD) &err, NULL);
WriteFile(hFile, (char *) &bmih, sizeof(BITMAPINFOHEADER), (LPDWORD) &err, NULL);
WriteFile(hFile, (char *) &bmi.bmiColors, sizeof(bmi.bmiColors), (LPDWORD) &err, NULL);
WriteFile(hFile, im_rgb, bmih.biSizeImage, (LPDWORD) &err, NULL);
CloseHandle(hFile);
}

Resources