|
I have a modeless dialog from which I display to two modal dialog boxes one after the other
I would like to save all the information I get from the two in the modeless dialog
So my plan was when creating the modal dialog box pass the Cwnd pointer using the this pointer
Well the first one seems to work by this I mean make breakpoint
abendialog = new RTMDialog(mylparam,this);
at the creation of the object and then at the contructor
RTMDialog::RTMDialog(LPARAM mylparam, CWnd* pParent)
: CDialog(IDD_DIALOG9, pParent)
at this pParent has valid pointer
In this dialog I create a second modal dialog
void RTMDialog::Percolate()
{
CMypercolate DOPREC(this);
DOPREC.DoModal();
}
here too the this pointer is valid however when I get to this constructer
pParent is null
CMypercolate::CMypercolate(CWnd* pParent )
: CDialog(IIDD_MYPERCOLATE, pParent)
{
|
|
|
|
|
Hardly surprising the question you need to ask yourself as a learning exercise
What is difference between instantiating an object using new vs. without
AKA there is a difference between these two things
abendialog = new RTMDialog(mylparam,this);
CMypercolate DOPREC(this);
The hint is where is the object put in the two different cases?
Hmmm your into your mutitasking so what is wrong with this which is the same thing
void SomeCreateCall (void){
char[256] data;
CreateThread(NULL, 0, SomeThreadFunction, (LPVOID)&data, 0, NULL);
}
The variable data above is obviously valid to pass so whats the problem and whats the fix?
In vino veritas
modified 23-Feb-18 2:52am.
|
|
|
|
|
The stack data or local data disappears once the functions exists
Thank so much
|
|
|
|
|
Correct pretty sure same thing is going to happen with your code, I wouldn't hold the dialog on the stack on a modeless dialog.
It's pretty dangerous to do, hold it as local data in the first dialog or on the heap same as you would on a multitask code
In vino veritas
|
|
|
|
|
Hello,
I wanted to communicate from one app (exe) to another app (exe) so I implemented COM interface in first application.
There are only .idl and some auto generated files (xxx.h & xxx.c) in first app but I dont know how to use this interface in another application.
Please guide.
|
|
|
|
|
|
Thanks for link.
Actually I am aware about the usage of COM but now problem is something different.
How to use COM interface defined in my first application which is an executable. It does not produce any dll or lib.
I need to give some reference to my second application to access same COM interface.
|
|
|
|
|
If you read those articles they explain how to link a COM client to the server.
|
|
|
|
|
Thanks,
Actually I got it. In my case it is .tlb file which I need to use to instantiate interface.
Now one more problem came
COCreateInstance() is returning REGDB_E_CLASSNOTREG Class not registered.
Do I need to register tlb file like a com dll?
If yes then how can do so?
|
|
|
|
|
Fedrer wrote: Do I need to register tlb file like a com dll?
You cannot register a TLB file.
However you have to register the COM component (that is the DLL ).
|
|
|
|
|
I am working with an ARM microcontroller and I'm programming in normal C programming language. I have a big array of struct, but a lot of the struct elements are unused and I would like to turn the array into an optimized struct/linked list instead. What would CLEAVER_MACRO_OR_PERHAPS_FUNCTION be in this case?
struct mySmallStruct1_s {
void* ptrToNextElement;
int myArray[1];
};
struct mySmallStruct2_s {
void* ptrToNextElement;
int myArray[2];
};
struct mySmallStruct3_s {
void* ptrToNextElement;
int myArray[3];
};
struct myBigStruct_s {
struct mySmallStruct1_s mySmallStruct1;
struct mySmallStruct2_s mySmallStruct2;
struct mySmallStruct3_s mySmallStruct3;
};
// This compiles fine, but I want something more reader-friendly
struct myBigStruct_s myBigStruct = {
{(void*)&myBigStruct.mySmallStruct2, {0}},
{(void*)&myBigStruct.mySmallStruct3, {0, 0}},
{(void*)0, {0, 0, 0}}
};
// What should CLEAVER_MACRO_OR_PERHAPS_FUNCTION be to make this compile?
struct myBigStruct_s myBigStruct2 = {
{CLEAVER_MACRO_OR_PERHAPS_FUNCTION(2), {0}},
{CLEAVER_MACRO_OR_PERHAPS_FUNCTION(3), {0, 0}},
{NULL, {0, 0, 0}}
};
|
|
|
|
|
You are making hard work of it, you have a C11 compiler
Unionize the struct pointers .. they are all pointers to different types
typedef union {
void* void_ptr;
struct mySmallStruct1_s* SmallStruct1_ptr;
struct mySmallStruct2_s* SmallStruct2_ptr;
struct mySmallStruct3_s* SmallStruct3_ptr;
} smallstruct_ptr;
struct mySmallStruct1_s {
smallstruct_ptr ptrToNextElement;
int myArray[1];
};
struct mySmallStruct2_s {
smallstruct_ptr ptrToNextElement;
int myArray[2];
};
struct mySmallStruct3_s {
smallstruct_ptr ptrToNextElement;
int myArray[3];
};
struct myBigStruct_s {
struct mySmallStruct1_s mySmallStruct1;
struct mySmallStruct2_s mySmallStruct2;
struct mySmallStruct3_s mySmallStruct3;
};
struct myBigStruct_s myBigStruct = {
{ .ptrToNextElement.SmallStruct2_ptr = &myBigStruct.mySmallStruct2, .myArray[0] = 0 },
{ .ptrToNextElement.SmallStruct3_ptr = &myBigStruct.mySmallStruct3, .myArray[0] = 0, .myArray[1] = 0 },
{ .ptrToNextElement.void_ptr = 0,.myArray[0] = 0,.myArray[1] = 0, .myArray[2] = 0 }
};
struct myBigStruct_s myBigStruct1 = {
{ .ptrToNextElement.SmallStruct2_ptr = &myBigStruct1.mySmallStruct2,.myArray[0] = 1 },
{ .ptrToNextElement.SmallStruct3_ptr = &myBigStruct1.mySmallStruct3,.myArray[0] = 1,.myArray[1] = 2 },
{ .ptrToNextElement.void_ptr = 0, .myArray[0] = 1,.myArray[1] = 2,.myArray[2] = 3 }
};
In vino veritas
|
|
|
|
|
I have a problem with redirect console app output and input. The problem is that any example I found does not work for me. I want to develop WPF GUI for a console app. This is the example code to redirect output:
ProcessStartInfo start = new ProcessStartInfo();<br />
start.FileName = "C:\\myapp.exe";
start.UseShellExecute = false;<br />
start.RedirectStandardOutput = true;<br />
using (Process process = Process.Start(start))<br />
{<br />
using (StreamReader reader = process.StandardOutput)<br />
{<br />
string result = reader.ReadToEnd();<br />
Console.Write(result);<br />
}<br />
}
So I did some reverse engineering on the console app and I found that this app is compiled using Microsoft Visual C 6.0. The app uses WriteFile to output to the console and first argument passed to the function equals 7.
I wrote the example code:
#include "stdafx.h"<br />
#include <windows.h><br />
<br />
int main()<br />
{<br />
AllocConsole();<br />
HANDLE hStdout;<br />
HANDLE hStdout2 = (HANDLE)0x00000007;<br />
char s[] = "Hello world !\r\n";<br />
char s2[] = "Hello world !CONOUT\r\n";<br />
char s3[] = "test\r\n";<br />
DWORD dwBytesWritten;<br />
<br />
HANDLE hScreenBuffer = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);<br />
<br />
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
WriteFile(hStdout2, s3, (DWORD)strlen(s3), &dwBytesWritten, NULL);
WriteFile((HANDLE)0x00000007, s3, (DWORD)strlen(s3), &dwBytesWritten, NULL);
WriteFile(hStdout, s, (DWORD)strlen(s), &dwBytesWritten, NULL);
WriteFile(hScreenBuffer, s2, (DWORD)strlen(s2), &dwBytesWritten, NULL);
<br />
FreeConsole();<br />
<br />
return 0;<br />
}
I do not understand why this: WriteFile(hStdout, s, (DWORD)strlen(s), &dwBytesWritten, NULL); (hStdout equals 7 checked by debuger) is redirected using my above example code or TestCON.exe > test.txt but this WriteFile((HANDLE)0x00000007, s3, (DWORD)strlen(s3), &dwBytesWritten, NULL); is printed always on the console.
Any suggestions how can I redirect any output to my GUI app?
|
|
|
|
|
It's in just about every AllocConsole example on the net
AllocConsole();
freopen("CONIN$", "r", stdin);
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
setbuf(stdout, NULL);
You may want to use the new freopen_s etc calls to avoid the warning.
CONIN$ and CONOUT$ are the console input and outputs associated to your program as distinct from the standard handles.
You may also care to read about console handles versus standard handles
Console Handles - Windows Console | Microsoft Docs[^]
That will give you the more modern way to do it via SetStdHandle and you should understand it now.
In vino veritas
modified 19-Feb-18 2:19am.
|
|
|
|
|
The problem is that I have only binary version console app that writes directly to the console.
Can you show me more completed code because maybe I miss something?
|
|
|
|
|
That isn't a problem you have redirected the standard file handle to the windows console created.
Try to read the console handles document and understand what is happening.
Visual studio does exactly that it executes a windows binary file and redirects the output to the console plane that is in visual studio.
Your binary file will use standard input/output and it's been redirected up to your console window.
You can also directly redirect spawned child applications
Creating a Child Process with Redirected Input and Output (Windows)[^]
That is if you want to do something like shellexecute a program and grab the output.
In vino veritas
modified 19-Feb-18 3:24am.
|
|
|
|
|
here see if this helps
It executes IPConfig and executes command.com to display a directory all redirected up to the windows console.
#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <thread>
using namespace std;
FILE* OutStream;
FILE* InStream;
FILE* ErrStream;
LRESULT CALLBACK GUIDemoHandler (HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch (Msg) {
case WM_CREATE:
AllocConsole();
freopen_s(&InStream, "CONIN$", "r", stdin);
freopen_s(&OutStream, "CONOUT$", "w", stdout);
freopen_s(&ErrStream, "CONOUT$", "w", stderr);
break;
case WM_DESTROY:
FreeConsole();
PostQuitMessage(0);
break;
default: return DefWindowProc(Wnd, Msg, wParam, lParam);
};
return 0;
}
int SystemCapture(
TCHAR* CmdLine,
TCHAR* CmdRunDir,
uint32_t& RetCode)
{
int Success;
SECURITY_ATTRIBUTES security_attributes;
HANDLE stdout_rd = INVALID_HANDLE_VALUE;
HANDLE stdout_wr = INVALID_HANDLE_VALUE;
PROCESS_INFORMATION process_info = { 0 };
STARTUPINFO startup_info = { 0 };
thread stdout_thread;
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
security_attributes.bInheritHandle = TRUE;
security_attributes.lpSecurityDescriptor = nullptr;
if (!CreatePipe(&stdout_rd, &stdout_wr, &security_attributes, 0) ||
!SetHandleInformation(stdout_rd, HANDLE_FLAG_INHERIT, 0)) {
return -1;
}
startup_info.cb = sizeof(STARTUPINFO);
startup_info.hStdInput = 0;
startup_info.hStdOutput = stdout_wr;
startup_info.hStdError = 0;
if (stdout_rd)
startup_info.dwFlags |= STARTF_USESTDHANDLES;
Success = CreateProcess(
nullptr,
CmdLine,
nullptr,
nullptr,
TRUE,
0,
nullptr,
CmdRunDir,
&startup_info,
&process_info
);
CloseHandle(stdout_wr);
if (!Success) {
CloseHandle(process_info.hProcess);
CloseHandle(process_info.hThread);
CloseHandle(stdout_rd);
return -4;
}
else {
CloseHandle(process_info.hThread);
}
if (stdout_rd) {
stdout_thread = thread([&]() {
DWORD n;
for (;;) {
const size_t bufsize = 256;
char buffer[bufsize];
n = 0;
int Success = ReadFile(
stdout_rd,
buffer,
(DWORD)bufsize-1,
&n,
nullptr
);
if (!Success || n == 0)
break;
buffer[n] = '\0';
printf(&buffer[0]);
}
});
}
WaitForSingleObject(process_info.hProcess, INFINITE);
if (!GetExitCodeProcess(process_info.hProcess, (DWORD*)&RetCode))
RetCode = -1;
CloseHandle(process_info.hProcess);
if (stdout_thread.joinable())
stdout_thread.join();
CloseHandle(stdout_rd);
return 0;
}
const TCHAR* ClassName = _T("GUI_CONSOLE_APP");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
MSG Msg;
HWND Wnd;
WNDCLASSEX WndClass = { 0 };
WndClass.cbSize = sizeof(WNDCLASSEX);
WndClass.style = CS_OWNDC;
WndClass.lpfnWndProc = &GUIDemoHandler;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = GetModuleHandle(NULL);
WndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(0, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = ClassName;
RegisterClassEx(&WndClass);
Wnd = CreateWindowEx(0, ClassName, _T("GUI Console Demo Program"),
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
50, 50, 500, 400,
0, 0, 0, NULL);
_tprintf(_T("This will go to the console\r\n"));
std::cout << "Second line to console\r\n" << std::endl;
std::cout << "Execute IPConfig and display result:" << std::endl;
int rc;
uint32_t RetCode;
TCHAR szCmdLine[256] = _T("C:\\Windows\\System32\\ipconfig.exe");
TCHAR szCmdDir[256] = _T(".");
rc = SystemCapture(
szCmdLine,
szCmdDir,
RetCode
);
std::cout << "\r\nExecute dir and display result:" << std::endl;
TCHAR szCmdLine1[256] = _T("cmd.exe /C dir");
rc = SystemCapture(
szCmdLine1,
szCmdDir,
RetCode
);
while (GetMessage(&Msg, 0, 0, 0)){
TranslateMessage(&Msg);
DispatchMessage(&Msg);
};
return (0);
}
In vino veritas
modified 19-Feb-18 5:13am.
|
|
|
|
|
Thank you for the example code.
The effect is that output from my console app is redirected when this app quits, but not when this app is running.
|
|
|
|
|
Your statement is also somewhat nonsensical in that when my sample app quits it destroys the console you wouldn't see it (see WM_DESTROY).
So I can only assume you mean your app you are running wont display until it exits????
So are you wanting live output keeping the app alive ???
You will have to spawn the thread before the call at the moment the program is
CreateProcess
Process output
That is the app must complete it's setup to deal with normal DOS like command files.
If it doesn't complete then the app will still be on the screen so why do you want it redirected to the console?????
In vino veritas
modified 19-Feb-18 12:30pm.
|
|
|
|
|
Okay so this spawns the thread before it executes the command passed in.
It should spit the console even if the command doesn't terminate, which I still find strange.
#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <tchar.h>
FILE* OutStream;
FILE* InStream;
FILE* ErrStream;
struct execData {
TCHAR* CmdLine;
TCHAR* CmdRunDir;
PROCESS_INFORMATION process_info;
STARTUPINFO startup_info;
};
struct execData data = { 0 };
LRESULT CALLBACK GUIDemoHandler (HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch (Msg) {
case WM_CREATE:
AllocConsole();
freopen_s(&InStream, "CONIN$", "r", stdin);
freopen_s(&OutStream, "CONOUT$", "w", stdout);
freopen_s(&ErrStream, "CONOUT$", "w", stderr);
break;
case WM_DESTROY:
if (data.process_info.hProcess) TerminateProcess(data.process_info.hProcess, 0);
FreeConsole();
PostQuitMessage(0);
break;
default: return DefWindowProc(Wnd, Msg, wParam, lParam);
};
return 0;
}
DWORD WINAPI ExecThreadFunction(LPVOID lpParam)
{
int Success;
struct execData* data = (struct execData*)lpParam;
Success = CreateProcess(
nullptr,
data->CmdLine,
nullptr,
nullptr,
TRUE,
0,
nullptr,
data->CmdRunDir,
&data->startup_info,
&data->process_info
);
if (!Success) {
CloseHandle(data->process_info.hProcess);
CloseHandle(data->process_info.hThread);
return -4;
}
else {
CloseHandle(data->process_info.hThread);
}
WaitForSingleObject(data->process_info.hProcess, INFINITE);
CloseHandle(data->process_info.hProcess);
data->process_info.hProcess = 0;
return (0);
}
int SystemCapture(
TCHAR* CmdLine,
TCHAR* CmdRunDir)
{
SECURITY_ATTRIBUTES security_attributes;
data.CmdLine = CmdLine;
data.CmdRunDir = CmdRunDir;
security_attributes.nLength = sizeof(SECURITY_ATTRIBUTES);
security_attributes.bInheritHandle = TRUE;
security_attributes.lpSecurityDescriptor = nullptr;
data.startup_info.cb = sizeof(STARTUPINFO);
data.startup_info.hStdInput = 0;
data.startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
data.startup_info.hStdError = 0;
data.startup_info.dwFlags |= STARTF_USESTDHANDLES;
CreateThread(NULL, 0, ExecThreadFunction, (LPVOID)&data, 0, NULL);
return 0;
}
const TCHAR* ClassName = _T("GUI_CONSOLE_APP");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
MSG Msg;
HWND Wnd;
WNDCLASSEX WndClass = { 0 };
WndClass.cbSize = sizeof(WNDCLASSEX);
WndClass.style = CS_OWNDC;
WndClass.lpfnWndProc = &GUIDemoHandler;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hInstance = GetModuleHandle(NULL);
WndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
WndClass.hCursor = LoadCursor(0, IDC_ARROW);
WndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
WndClass.lpszMenuName = NULL;
WndClass.lpszClassName = ClassName;
RegisterClassEx(&WndClass);
Wnd = CreateWindowEx(0, ClassName, _T("GUI Console Demo Program"),
WS_VISIBLE | WS_OVERLAPPEDWINDOW,
50, 50, 500, 400,
0, 0, 0, NULL);
_tprintf(_T("This will go to the console\r\n"));
std::cout << "Second line to console\r\n" << std::endl;
int rc;
TCHAR szCmdDir[256] = _T(".");
std::cout << "\r\nExecute console app:" << std::endl;
TCHAR szCmdLine1[256] = _T("ConsoleApp.exe");
rc = SystemCapture(
szCmdLine1,
szCmdDir
);
while (GetMessage(&Msg, 0, 0, 0)){
TranslateMessage(&Msg);
DispatchMessage(&Msg);
};
return (0);
}
I made a strange console app that just spins the cursor to test it worked which was called ConsoleApp.exe hence my name above
static const char Spin[4] = { '|', '/', '-', '\\' };
int main()
{
int i = 0;
while (1) {
printf("Deadloop %c\r", Spin[i]);
for (long j = 0; j < 10000000; j++) {};
i++;
i %= 4;
}
return 0;
}
In vino veritas
modified 19-Feb-18 13:37pm.
|
|
|
|
|
I am checking it using test app with WriteFile function and it works. But I will check it using target app tomorrow because it needs some hardware to work.
Thanks
|
|
|
|
|
This code is working.
Now I will try to analyze outputs and build GUI.
I am not sure if can I use the code in C# WPF application. If not I will try to build GUI using Win API starting from your examples. Thank you.
|
|
|
|
|
It's a simple background worker thread it will work without issue in a C# WPF application.
How to: Use a Background Worker[^]
Inside the worker thread you want a standard command execute
static void runCommand() {
Process process = new Process();
process.StartInfo.FileName = "cmd.exe";
process.StartInfo.Arguments = "/c yourfile.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) {
Console.WriteLine(outLine.Data);
}
In vino veritas
modified 20-Feb-18 2:21am.
|
|
|
|
|
I do simple test and problem is the same as before. Only when console app quits OutputHandler is executed and then I can read every line by line that app prints during running. Furthermore, it seems that StandardInput is not redirected because click on the button does not quit the app. App quits when 'e' key is pressed in the console window.
public partial class MainWindow : Window
{
Process process = new Process();
public MainWindow()
{
InitializeComponent();
runCommand();
}
private void button_Click(object sender, RoutedEventArgs e)
{
textBox.Text += "test\r\n";
process.StandardInput.Write('e');
}
void runCommand()
{
process.StartInfo.FileName = "c:\\ConsoleApp.exe";
process.StartInfo.Arguments = ".";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
}
void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
{
Console.WriteLine(outLine);
}
}
|
|
|
|
|
Yes because you didn't put it in a worker thread
You need runCommand() to be in a worker thread .. it has to execute in the background so you can keep the WPF framework running in the foreground.
Look back at the windows code I had to do the same thing the CreateProcess(...) is inside a function which is spawned into it's own thread via CreateThread.
Unfortunately I don't use C# enough to know the code for making a worker thread off the top of my head.
I actually don't have the WPF framework installed on my VisualStudio at the moment to work it out.
Basically however we can describe it
1.) everything in runCommand() needs to go inside the worker thread start function .. when the thread starts it runs the app
2.) When the app finishes or your WPF app finishes you need to close the worker thread (LOOK at WM_DESTROY on the windows code)
So basically this worker thread will be chugging along in the background running the app but your program comes back to you to continue on to run the WPF framework.
So you job is to work out how to make a WPF worker thread and incorporate the code
In vino veritas
|
|
|
|
|