I have tried multiple things but the base comes to this:
#include <stdio.h>
#include <afxwin.h>
main( int argc, const char* argv[] )
{
printf( "\nHello World\n\n" );
CDialog *dlg = new CDialog();
dlg->DoModal();
while (true) {
Sleep(1); // Sleep is a windows function
}
}
When I run this, I get the following error:
What am I missing for this dialog?
I looked up several resources, but everything results in the same error message.
Can someone tell me what am I not seeing?
Using the MFC in a console application requires some initializations.
Without this you will get asserts.
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
return 8;
}
You must also use a resource that is bound to the CDialog. You may use the appropriate constructors. Or you derive your own dialog from CDialog using the class wizard.
But it doesn't make sense to me to create an MFC console application and use dialogs... Your question may need more details, what you want to do, and why you want to do it in this way.
You may need to read some books or article before you continue this way of programming.
Related
I'm trying to interface with the xfce4-settings-manager which I was successfully able to do in the standard c gtk+-3.0 libraries, but I've been struggling to replicate it in gtkmm3. xfce4-settings-manager passes a --socked-id option to the client, and the client is meant to use a GtkPlug to connect to the socket via the id. As I mentioned before I was successful in writing it in C, and I've put that code in a github gist here. I prefer to use C++ as a means to learn the language in a more applied way and also because of its higher functionality to C.
I've struggled with the proper way to handle arguments to the proper way to use Gtk::Plug with hours of research and little results. If anyone can provide some insight into the proper way/documentation to handle command line arguments and GtkPlugs in gtkmm3 that would be greatly appreciated, and if you could provide any examples that would also be greatly appreciated. Thank you in advance!
Here is an example similar to yours, in C++ with Gtkmm 3:
#include <string>
#include <gtkmm.h>
#include <gtkmm/plug.h>
// Simple command line argument parser.
//
// Documented here:
//
// https://gitlab.gnome.org/GNOME/glibmm/-/blob/master/examples/options/main.cc
//
class CmdArgParser : public Glib::OptionGroup
{
public:
CmdArgParser(const std::string& p_name, const std::string& p_description, const std::string& p_help)
: Glib::OptionGroup{p_name, p_description, p_help}
{
// Define the 'socket ID' argument options:
Glib::OptionEntry socketIDArg;
socketIDArg.set_long_name("socket-id");
socketIDArg.set_short_name('s');
socketIDArg.set_flags(Glib::OptionEntry::FLAG_IN_MAIN);
socketIDArg.set_description("Settings manager socket");
// Register it in the parser. It value will be recorded in m_socketID for later usage.
add_entry(socketIDArg, m_socketID);
}
// Override this to handle errors. I skipped it for simplicity.
// void on_error(Glib::OptionContext& context, const Glib::Error& error) override;
::Window GetSocketID() const
{
return m_socketID;
}
private:
int m_socketID = 0;
};
// This is what is going to be plugged into xfce4-settings-manager:
//
// Documented here:
//
// https://developer.gnome.org/gtkmm-tutorial/3.22/sec-plugs-sockets-example.html.en
//
class SettingsPlug : public Gtk::Plug
{
public:
SettingsPlug(::Window p_socketID)
: Gtk::Plug{p_socketID}
{
m_button.set_label("A plug with Gtkmm3!");
add(m_button);
show_all_children();
}
private:
Gtk::Button m_button;
};
int main(int argc, char** argv)
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example.plug");
// Parse command line arguments and retreive socket ID:
Glib::init();
setlocale(LC_ALL, "");
Glib::OptionContext context;
CmdArgParser parser{
"Socket ID",
"Command line argument for socket ID communication.",
"No help available, sorry"
};
context.set_main_group(parser);
context.parse(argc, argv);
::Window socketID = parser.GetSocketID();
// Handle plug:
SettingsPlug plug{socketID};
plug.show();
app->run(plug);
return 0;
}
I have removed error handling and the usage of Glade files to simplify the code. You can build it with:
g++ main.cpp -o example.out `pkg-config --cflags --libs gtkmm-3.0`
Original Post
I have a Qt application. This application needs to call some function in a dynamic library that is loaded implicitly. In the dynamic library, there is one global variable that is created when the dll is loaded and destroyed when it is unloaded.
Here's the code:
#include <QApplication>
#include <base/BASE_TEST.h>
int main(int qargc, char** qargv)
{
QApplication application(qargc, qargv);
BASE_TEST::myDLLFunction(); // call to a function in an implicitly loaded dynamic library.
return 0;
}
Implementation of myDLLFunction and of the private class of the global object.
#include <base/BASE_TEST.h>
#include <stdio.h>
class MyTest
{
public:
MyTest() { printf("------------------------------\nTEST BEGIN\n------------------------------\n"); }
~MyTest() { printf("------------------------------\nTEST END\n------------------------------\n"); }
};
MyTest test; // created at the library's loading
void BASE_TEST::myDLLFunction()
{
printf("Call from dynamic library\n");
}
If I run the application, here's what being printed in the command prompt:
------------------------------
TEST BEGIN
------------------------------
Call from dynamic library
------------------------------
TEST END
------------------------------
Up to here all is well. However, if I retrieve some information about the number of screens using QApplication::desktop(), the global object of the dynamic library isn't destroyed.
int main(int qargc, char** qargv)
{
QApplication application(qargc, qargv);
QDesktopWidget* desktop = QApplication::desktop(); // This call prevent the global objects to be destroyed.
BASE_TEST::myDLLFunction(); // call to a function in an implicitly loaded dynamic library.
return 0;
}
Here's what is printed in the command prompt:
------------------------------
TEST BEGIN
------------------------------
Call from dynamic library
The main function still returns normally and no exception is thrown.
I looked at the code of QApplication and QDesktopWidget and the QDesktopWidget destructor is being called at the end of the main function's scope and QDesktopWidgetPrivate::cleanup() is called.
I'm on Windows, using Qt 4.8.6.
Does someone has any idea?
Thanks! :)
Edit
As mentionned in the answer below, the problem seems to be linked to loading wintab32.dll which will load the Wacom driver's dynamic library if installed.
I finally found the source of the issue:
Calling QApplication::desktop() made Wacom_Tablet.dll be loaded. By uninstalling the Wacom driver, the problem went away.
I was able to reduce the sample program to:
#include "../baseTest/BASE_TEST.h"
#include <wtypes.h>
#include "wintab.h"
typedef UINT(WINAPI *PtrWTInfo)(UINT, UINT, LPVOID);
static PtrWTInfo ptrWTInfo = 0;
int main(int /*qargc*/, char** /*qargv*/)
{
BASE_TEST::myDLLFunction(); // call to a function in an implicitly loaded dynamic library.
HMODULE hWintab = LoadLibrary(L"wintab32.dll");
PtrWTInfo pWTInfo = (PtrWTInfo)GetProcAddress(hWintab, "WTInfoW");
WORD thisVersion;
pWTInfo(WTI_INTERFACE, IFC_SPECVERSION, &thisVersion);
if (hWintab)
FreeLibrary(hWintab);
return 0;
}
and still be able to reproduce the issue.
I've contacted Wacom about it and am waiting their reply.
I'm unable to get command line argument with int main(int argc, char* argv[]), No errors occurs but when further manipulation want to happen i see that argv[ ] and other related variables dont have any value and says Error reading characters of string then an Acces violation reading location error happens.
This is the sample code of my issue, I had to downsize it to make it readable:
#include "CommonHeaders.h"
void Start(char *input)
{
lstrcpyA(host, input);
// In this point i see in my Debugger "Locals/Autos" that nothing
// is passed to function then a "Access violation ... " happens.
// ...
}
int main(int argc, char *argv[])
{
Start(argv[1]);
return 0;
}
I always use this int main(int argc, char* argv[]) and pass command arg with ProjectProperties->Debugging->Command Argument and works perfect everytime. Is it possible that proper headers aren't included or any changes in project configuration could make a conflict?
Be sure to set the subsystem to console Linker -> SubSytem -> Console (/SUBSYSTEM:CONSOLE) and dont set an Entry point set the Whole Program Optimization to No Whole Program Optimization and turn SDL check to off.
everybody.
I am working on a gtkmm app and need some help getting a "Close" button to work. As suggested by the gtkmm documentation, I derived a class for the main window object, created some members, and left the main() function mostly for reading the glade UI file, instantiating the form and starting the main loop.
There are 3 files, named conveniently for explanation: Declarations.h, Declarations.cpp, Program.cpp
In "Declarations.h" I have the class inherited from the Gtk Window:
#include <gtkmm.h>
class MainWindowClass : public Gtk::ApplicationWindow
{
protected:
Gtk::Button *button_close;
// other buttons here
protected:
void on_button_close_clicked();
// other callback functions here
public:
MainWindowClass(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade); // Constructor
// Destructor, other public members
};
In "Declarations.cpp" I have the implementations:
#include "Declarations.h"
using namespace Gtk;
// Implementing the constructor
MainWindowClass::MainWindowClass(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) :
Gtk::Window(cobject), builder(refGlade)
{
builder->get_widget("button_close", button_close);
// Getting other widgets from the glade file
button_close->signal_clicked().connect(sigc::mem_fun(*this, &MainWindowClass::on_button_close_clicked));
// Connecting other callback functions here
}
// Implementing the callback for the "Close" button, ** PROBLEM IS HERE **
void MainWindowClass::on_button_close_clicked()
{
//gtk_main_quit(); Apparently GTK+/C only, compiler doesn't complain but causes a segfault when clicking the button
//Gtk::Application::quit(); Won't compile
}
The Program.cpp reads the UI from a file and starts the main program loop:
#include <gtkmm.h>
#include "Declarations.h"
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "Damn this close button");
Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file("Program_UI.glade");
MainWindowClass our_main_window;
return app->run(our_main_window);
}
I am omitting some non-relevant code (of other objects and callbacks) because they work, it is the close procedure that is causing me trouble, though closing the app with "X" works.
I have also thought about trying to call a quit() or destroy() function (if they exist) of "app", but then the callback function doesn't know "app" exists.
What do you guys suggest?
Thanks a lot.
** Edit: fixed this using FormMain::hide(), which is inherited from GtkWindow.
I thought the static procedure Gtk::Main::hide() would do it, but the compiler says that hide() is not a member of Gtk::Main...
Well, moving forward one step at a time.
Used FormMain::hide() (inherited from GtkWindow). The static procedure Gtk::Main::hide() was not being recognized by the compiler.
Any call on my application to AfxGetApp() returns NULL, can anyone help?
It is a .exe project converted from a .dll project, so there may be some project configurations that I am missing. I have copied configurations from another project created with the .exe wizard but is does not work. Also, I have a CWinApp that is global.
Check your preprocessor definitions. Remove _AFXEXT.
I had a similar problem building a dll, if I copy this code (taken from another dll) AfxGetApp() returns the correct pointer:
CWinApp theApp;
using namespace std;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
}
return nRetCode;
}