so I made a C program that imitates a ATM except you can create bank accounts in it. But when the user quits the application, the application loses all values, so they have to recreate the account, and redo all their settings.
I have tried to look this up by Googling it and consulting C programming books but I haven't found anything. So is there any code to minimize the console screen from within the program so that the application doesn't actually close and lose all the values? Any help is greatly appreciated.
If you only want to minimize the console window you have to:
#include <Windows.h>
Use the block below:
/* the following code minimizes the console window */
{
char szTitle[256];
HWND hConsole = NULL;
memset(szTitle, 0, sizeof(szTitle));
/* get the console window's title */
GetConsoleTitle((LPWSTR)szTitle, 256);
/* get the HWND windows handle of the console window by looking up for
windows with szTitle as title*/
hConsole = FindWindow(NULL, (LPWSTR)szTitle );
/* "show" it as minimzed */
ShowWindow(hConsole, SW_MINIMIZE);
}
Hope it helps!
it's called Database. you can save all your records into a file(any kind you want) and you need to read that file when application start and build your data set.
for example:
if you have a record for each account containing name, id, balance, then you can save before closing to a normal .txt, say "C:\tmp\DB.txt" file all the records as ,,* string for each record.
upon entering the application you'll check if a file "C:\tmp\DB.txt" exist and if so read it and build the data accordingly.
back to your question. it is possible to just minimize the program when pressing the close button in winforms for windows and in other ways for other languages. It might be possible to do it in c, though i doubt it. anyway it makes no sense, because the user can still kill the process despite your efforts and thus make it not worthwhile to do it
Related
I have an unrepeatable bug of unknown origin in my single threaded window manager that occurs fairly infrequently (once every 2-3 weeks). Something happens that causes me to lose keyboard input. Mouse events are still handled properly so I know the event loop is still running, but the key press event is no longer triggered. Actually, the key is no longer grabbed. When I press XCB_MOD_MASK_4+2 to switch to desktop 2, the 2 will show up in the text editor or terminal that currently has the input focus, instead of being grabbed by the window manager. I thought maybe it was related to xcb_allow_events, so via IPC I can execute these three tests (from within the window manager, cmd is received from an external process):
if (strcmp(cmd,"test0")==0)
xcb_allow_events(wm.conn, XCB_ALLOW_ASYNC_KEYBOARD, XCB_CURRENT_TIME);
else if (strcmp(cmd,"test1")==0)
xcb_allow_events(wm.conn, XCB_ALLOW_SYNC_KEYBOARD, XCB_CURRENT_TIME);
else if (strcmp(cmd,"test2")==0)
keyboard();
void keyboard()
{
int i,m,k;
xcb_void_cookie_t cookie;
spawn("/usr/bin/xmodmap -e 'keycode 108 = Super_L'");
spawn("/usr/bin/xmodmap -e 'remove mod1 = Super_L'");
for (i=0; i<LENGTH(key_bindings); i++)
{
m = key_bindings[i].mod;
k = keysc(key_bindings[i].keysym);
info("grabbing key: %s (%d), mod: %d",key_bindings[i].keysym,k,m);
cookie = xcb_grab_key_checked(wm.conn, 0, wm.root, m, k, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
if (xcb_request_check (wm.conn, cookie))
error("can't grab key");
}
}
None of these tests help. I know the keyboard function works properly because it works on window manager startup. Also I can see in the log file that the key grabs in the keyboard function are actually being executed (without error) when prompted via IPC. The current workaround is to send sigterm to the window manager process, and then restart the wm. At that point everything works fine again.
I'm looking for techniques that might be helpful in tracking down the source of this problem, or in correcting the problem once it occurs (another test). Unfortunately, since I have no clue of the source of this problem, or what triggers it, I cannot make a simple test case to demonstrate. BTW I check the log files when this happens, and I don't see any pattern leading up to the problem. Each function logs an entry on entrance and exit.
Update 2021-02-12: I thought a restart would be a good workaround until I found the root cause of this problem. My restart function contains only one line:
execvp(lwm_argv[0], lwm_argv);
where lwm_argv is the argv provided as an argument to main.
I was very surprised to see that this did not alleviate the problem. I have to completely kill the old process then launch an new one to alleviate the problem. So this problem is PID dependant??? Further, I'm fairly convinced that this problem is somehow related to the stdout/stderr output of other applications launched from within the window manager using execvp. I've stopped launching applications from within the window manager and the problem went away. Any ideas of how launching other applications (and their output) could be affecting the keygrabs within the window manager would be appreciated.
You could try using strace or perf trace on the X server to see what it is doing with the key events. It ought to read them from somewhere in /dev/input and send them as events to connected clients.
If it isn't sending you events, then you might need to dig into its internal state, perhaps by building a debug server and connecting to it with GDB, to see why it isn't sending those events.
But if it is sending events to your WM then they're getting lost somewhere in the library stack.
I want to log if a customer tries to force close the application. I'm aware of having no chance to catch a process kill. But it should be possible through the main form closing event to get informed about the 'CloseReason.TaskManagerClosing' reason.
But any tests I did under Windows 8.1 I always got a CloseReason.UserClosing reason. But in this case (compared to a normals CloseReason.UserClosing) I've about 0.2s to run user code afterwards my program is killed!
Is this a new behavior in Windows 8.1?
Yes, I see this. And yes, this is a Windows change, previous versions of Task Manager sent the window the WM_CLOSE notification directly. I now see it issue the exact same command that's issued when you close the window with the Close button (WM_SYSCOMMAND, SC_CLOSE). Or press Alt+F4 or use the system menu. So Winforms can no longer tell the difference between the Task Manager and the user closing the window and you do get CloseReason.UserClosing.
What happens next is expected, if you don't respond to the close command quickly enough then Task Manager summarily assassinates your program with TerminateProcess().
Do keep in mind that trying to save data when the user aborts your program through Task Manager is a bad practice. Your user will normally use this if your program is malfunctioning, you can't really trust the data anymore and you risk writing garbage. This is now compounded by your saving code being aborted, high odds for a partially written file or dbase data that isn't usable anymore.
There is no simple workaround for this, the odds that Windows is going to be patched to restore old behavior are very close to zero. It is very important that you save your data in a transactional way so you don't destroy valuable data if the saving code is aborted. Use File.Replace() for file data, use a dbase transaction for dbase writes.
An imperfect way to detect this condition is by using the Form.Deactivate and Activate events. If you saw the Deactivate event and the FormClosing event fires then reasonable odds that another program is terminating yours.
But the normal way you deal with this is the common one, if the user ends the program without saving data then you display a dialog that asks whether to save data. Task Manager ensures that this doesn't go further than that.
Another solution for determining when the Task Manager is closing the program is by checking if the main form, or any of its controls, has focus. When you close via the Task Manager, the application is not focused, whereas if you close via the close button or Alt+F4, the application does have focus. I used a simple if check:
private void MyForm_Closing(object sender, FormClosingEventArgs e)
{
if (this.ContainsFocus)
{
// Put user close code here
}
}
I am replacing many batch files, that do almost the exact same thing, with one WPF executable. I have the program written, but I am having troubles with my "console" like display.
Within the program I call an executable to perform a task. This executable sends it's output messages to the console. I am able to redirect those to my "console" like display with the following.
Process p = new Process();
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.FileName = MyExecutable;
p.StartInfo.Arguments = MyArguments;
p.Start();
while (!p.StandardOutput.EndOfStream)
{
string _output = p.StandardOutput.ReadLine();
// This is my display string ObservableCollection
_displayString.Add(new DisplayData { _string = _output, _color = System.Windows.Media.Brushes.Black, _fontSize = 12 });
// This is to redirect to a Console & what I want to get rid of
Console.WriteLine(_output);
}
p.WaitForExit();
When the executable is done running I use a MessageBox to ask the user if they want to run the executable again. The problem is that when the MessageBox is up the user is unable to scroll on my "console" like window to make an informative decision. To temporarily work around this I launch a console at start up, see this, and write the output stream from the process running the executable to the console so the user can scroll through the information and make a decision.
I am using a listbox to display a collection of textblocks, see this. I am not attached to anything for making the display, or MessageBox'es.
How can I make a "console" like display that will take a user input (MessageBox, direct input, etc...), but also allow them to scroll through the data before they make their decision?
EDIT:
As to the comments I have been receiving I am not clear on what I am trying to accomplish. I have a batch file that runs a executable multiple times with different arguments per run. There is a lot of setup before and between the executable calls. I have created an executable to replace many flavors of a similar batch file with drop down menus for the user to change settings at run time. When the user likes their settings they click a "Start" button, and away it goes doing setups and prompting questions as it goes and then finally runs executable for the first time.
My issue is when the called executable, inside mine, is done running the user needs to decide if they want to run it again for different reasons. I need to prompt the user "Run again - 'Yes' or 'No'?", and that is where I am running into problems. A MessageBox doesn't allow me to scroll on my Progress Window. I have tried a Modeless dialog box, but with Show() the program continues on, and ShowDialog() is the same issue as the MessageBox.
Any suggestions on how to do this would be appreciated.
You are in Windows, but trying to use DOS paradigm. Windows is event-based system! You need to write "event handlers" but not put all your code in one function.
However, there is a trick, which allows to show Modal (read "blocking your code") dialog in Modeless (read "not blocking your window"). Not sure how to implement this in WPF, but idea is to re-enable your window (which acts as parent for your dialog). You need to do this in your dialog event handler (WM_INITDIALOG equivalent?).
Also (in WinAPI) you may run dialog with NULL as parent window.
I wrote a large complex C program around 20(!) years go. As far as I can recall it worked fine at the time in all respects - it was probably running on windows 95.
Now I need to use it again. Unfortunately the radio buttons in it do not appear to work properly any more (the ordinary push buttons are all behaving correctly). As I click on the radio buttons, I get some feedback that windows is acknowledging my click in as much as I see a dotted line appear around the button's text and the circle of the button goes grey for as long as my finger is on the button, but when I take my finger off I see that the selected button has not changed.
My suspicion is that I was perhaps getting away with some bad practice at the time which worked with windows 95 but no longer works on newer versions of windows, but I'm struggling work out what I did wrong. Any ideas?
EDIT: Its difficult to extract the relevant code because the message handling in this program was a tangled nightmare. Many buttons were created programatically at runtime and there were different message loops working when the program was in different modes of operation. The program was a customisable environment for running certain types of experiment. It even had its own built-in interpreted language! So I'm not expecting an answer like "you should have a comma instead of a semicolon at line 47", but perhaps something more like "I observed similar symptoms once in my program and it turned out to be ..... " .. or perhaps "the fact that the dotted rectangle is appearing means that process AAA has happened, but maybe step BBB has gone wrong".
EDIT: I've managed to extract some key code which my contain an error...
char *process_messages_one_at_a_time()
{
MSG msg;
int temp;
temp = PeekMessage(&msg,winh,0,0,PM_NOREMOVE);
if (temp)
{
GetMessage (&msg, NULL, 0, 0);
if (msg.message == WM_LBUTTONUP)
{
mouse_just_released_somewhere = TRUE;
}
TranslateMessage (&msg);
DispatchMessage (&msg);
}
if (button_command_waiting)
{
button_command_waiting = FALSE;
return (button_command_string);
}
else
{
return (NULL);
}
}
There are two simple things to check when using radio buttons. First is to make sure that each has the BS_AUTORADIOBUTTON property set. The second is to make sure that the first button in the tab order and the next control after the set of buttons (typically a group box) have the WS_GROUP property set, while the other buttons have it clear.
A few suggestions:
I'd try to use spy++ to monitor the messages in that dialog box, particularly to and from the radiobutton controls. I wonder if you'll see a BM_SETCHECK that your program is sending (ie, somewhere you're unchecking the button programatically).
Any chance your code ever checks the Windows version number? I've been burned a few times with an == where I should have used a >= to ensure version checking compatibility.
Do you sub-class any controls? I don't remember, but it seems to me there were a few ways sub-classing could go wrong (and the effects weren't immediately noticeable until newer versions of Windows rolled in).
Owner-drawing the control? It's really easy to for the owner-draw to not work with newer Windows GUI styles.
Working with old code like that, the memories come back to me in bits and pieces, rather than a flood, so it usually takes some time before it dawns on me what I was doing back then.
If you just want to get the program running to use it, might I suggest "compatibility mode".
http://www.howtogeek.com/howto/windows-vista/using-windows-vista-compatibility-mode/
However, if you have a larger, expected useful life of the software, you might want to consider rewriting it. Rewriting it is not anywhere near the complexity or work of the initial write because of a few factors:
Developing the requirements of a program is a substantial part of the required work in making a software package (the requirements are already done)
A lot of the code is already written and only parts may need to be slightly refactored in order to be updated
New library components may be more stable alternatives to parts of the existing codebase
You'll learn how to write current applications with current library facilities
You'll have an opportunity to comment or just generally refactor and cleanup the code (thus making it more maintainable for the anticipated, extended life)
The codebase will be more maintainable/compatible going forward for additional changes in both requirements and operating systems (both because it's updated and because you've had the opportunity to re-understand the entire codebase)
Hope that helps...
I'd like to intercept the WM_DELETE_WINDOW message that is posted to a certain selection of windows that an application I'm writing (AllTray), so that I can act on it instead of the application receiving it. I'm currently looking at trying this at the GDK level via gdk_display_add_client_message_filter if possible, but I'd be happy with an Xlib solution if there is one as well; it seems to be possible, but I just don't seem to be understanding how I am to do it successfully.
Currently, I have two programs (written in C) that I am trying to use to get this figured out, the first one does nothing but create a window and register that it knows about WM_DELETE_WINDOW, and the second one attempts to catch that message, but seems to fail in doing so; it appears to do precisely nothing. Am I understanding the documentation wrong on this, or is there something additional that I need to be doing (or do I need to avoid using GDK entirely for this)?
The background is this: Prior to my re-write of AllTray, the way it would do things appears to be to try to intercept a mouse-click on the X button itself. For some window managers, this worked properly, for others it didn't work at all, and for others, the user had to configure it manually and instruct AllTray where the button for closing the window was. What I am looking for is a solution that doesn't involve a LD_LIBRARY_PRELOAD and will work for any window manager/application combination that conforms to the current standards and sends a WM_DELETE_WINDOW ClientMessage when the window is closed.
UPDATE: I'm still looking for an answer. The route that I am taking at the moment is to try to reparent the window and manage it myself, but I just cannot make it work. Upon reparenting, I don't seem to be able to get it back in any way. I may be missing something very fundamental, but I can't figure out how to actually make it appear it my own window again, to bring it back on the screen.
UPDATE 2: Alright, so I've hit another brick wall. The X server documentation says to set the StructureNotifyMask on the window's event mask to receive both MapNotify and ReparentNotify events. I'd be interested in receiving either. My current thinking was to create a window that served just as an event receiver, and then when I get events for interesting things, act on them by creating and reparenting. However, this simply doesn't seem to be working. The only events I actually receive are PropertyNotify events. So, this route doesn't seem to be doing very much good, either.
I don't know X11, but I googled using "Intercept WM_DELETE_WINDOW X11" as keywords. Found 17k - MarkMail and Mplayer-commits r154 - trunk/libvo. In both cases they are doing the same thing.
/* This is used to intercept window closing requests. */
static Atom wm_delete_window;
within static void x11_init(),
XMapWindow(display, win);
wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, win, &wm_delete_window, 1);
then, within static int x11_check_events(),
XEvent Event;
while (XPending(display)) {
XNextEvent(display, &Event);
if (Event.type == ClientMessage) {
if ((Atom)Event.xclient.data.l[0] == wm_delete_window) {
/* your code here */
}
}
}
See XInternAtom, XSetWMProtocols and XNextEvent.
After I wrote the above, I found Handling window close in an X11 app:
When a user clicks the close button
[x] on our X11 application we want it
to pop a a dialog asking “do you
really want to quit?”. This is a plain
X app. No fancy GTK or QT widgets
here. So how to catch the “window is
being closed” message?
The answer is to tell the Window
Manager we are interested in these
event by calling XSetWMProtocols and
registering a WM_DELETE_WINDOW message
with it. Then we’ll get a client
message from the Window Manager if
someone tries to close the window, and
it won’t close it, it’ll leave that us
up to us. Here’s an example….
// example.cpp
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <iostream>
int main()
{
Display* display = XOpenDisplay(NULL);
Window window = XCreateSimpleWindow(display,
DefaultRootWindow(display),
0, 0,
500, 400,
0,
0, 0);
// register interest in the delete window message
Atom wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(display, window, &wmDeleteMessage, 1);
std::cout << "Starting up..." << std::endl;
XMapWindow(display, window);
while (true) {
XEvent event;
XNextEvent(display, &event);
if (event.type == ClientMessage &&
event.xclient.data.l[0] == wmDeleteMessage) {
std::cout << "Shutting down now!!!" << std::endl;
break;
}
}
XCloseDisplay(display);
return 0;
}
Unfortunately, the best answer to this question is a series of non-answers; there are technically ways to accomplish it, but they all have downfalls that make them extremely impractical:
Create an X11 proxy for an application, passing all X11 protocol messages back and forth between the application and the X server. The proxy would then filter out any interesting messages. The downside to this is that this is an awful lot of overhead for a single little tiny feature, and the X11 protocol is complex. There could also be unintended consequences, which makes this an even more unattractive option.
Launch as a standard application that acts as an intermediary between the window manager and “interesting” client applications. This breaks some things, such as XDnD. In effect, it is not unlike the first option, except that the proxy is at the Window level as opposed to the X11 protocol level.
Use the non-portable LD_PRELOAD library trick. This has several downsides:
It is non-portable across dynamic linkers: not all dynamic linkers support LD_PRELOAD, even among UNIX-like systems.
It is non-portable across operating systems: not all operating systems support featureful dynamic linkers.
It breaks network-transparency: the shared object/dynamic link library must reside on the host as the child process that is being executed.
Not all X11 applications use Xlib; it would be necessary to write one LD_PRELOAD module for each of the libraries that an application might use to talk with X11.
In addition to the last point, not all applications would be susceptible to LD_PRELOAD even if they ran under a linker that supported it, because they may not use a shared object or DLL in order to communicate with X; consider, for example, a Java application which uses an X11 protocol library written in Java itself.
On some UNIX-like operating systems, LD_PRELOAD libraries must be setuid/setgid if they are to be used with setuid/setgid programs. This is, of course, a potential security vulnerability.
I am quite sure that are more downsides that I cannot think of.
Implement an extension to the X Window system. Non-portable among X11 implementations, complex and convoluted as all get out, and absolutely out of the question.
Implement extensions or plug-ins to window managers. There are as many window managers as there are opinions on window managers, and therefore this is utterly infeasible.
Ultimately, I was able to finally accomplish my goal by using a completely separate mechanism; anyone who is interested, please see the Close-to-Tray support in AllTray 0.7.5.1dev and later, including the git master branch available on github.
Ok, to elaborate on my earlier suggestion, you might want to investigate XEmbed. At the least, that might give you some ideas to try.
Failing that, I'd have a look at how other similar software might be working (e.g. wmdock, or how GtkPlug/GtkSocket is implemented), though I believe in both those cases explicit support is required in the applications.
Hope that is more helpful.
You should read ICCCM that tells you how window manager communicates with client. Most of WM will create a frame window to contain your top-level window via reparenting. Thus, if your reparent may break the relationship known by WM and your client window.