MFC CEdit Ctrl Question - c++

I have a CEdit control that I want to be able to take time input from. Now I want this input to come in the form hh:mm:ss. Currently I am using a separate CEdit control for hour, mins, & secs. I know I could require the user enter in colons to separate hours, mins, secs, but this I believe will get confusing for my users.
I actually want my control to show the colons, and have the different sections of the control to be tab stops, so that it is clear to the user what time exactly they are entering in. I know I have seen this elsewhere, and I just don't know how to do it myself.
Ideally these would come in as 3 separate strings, because I am not using Epoch time, or any other type of system time, but am using my own time count. (ie. how many data samples we are into the file.) Meaning each time, my clock starts at zero, and counts up from there.
Thanks
Dan

Reformatting the text is simple enough, although I would wait until a lost focus message rather than insert colons while the user is typing, it gets confusing especially if they need to edit or delete a character.
You can implement tab stops within the field by getting VK_TAB but I'm not sure I would do this - users are used to tabs jumping to the next control not to positions within a control.
Another way to do this is to have 3 separate controls but detect when the user has entered enough characters for the first, or entered a tab (or colon) and then automatically switch focus to the next one. I think this is neater, it's what the IP_ADDRESS control does.

You'll have to handle each WM_CHAR (or WM_KEYUP, as appropriate) and re-format the text in the edit box as the user types. Handle the message for VK_TAB and set the selection as appropriate.

Related

SAS Enhanced Editor: Submitting code block without manually highlighting

Very rarely do I ever need to submit an entire .sas file. Instead, I submit steps one at a time. This means I am constantly highlighting code.
Question: Is there a way to have SAS submit a block of code without manually highlighting it?
Scratch Work:
Emacs ESS has the "Evaluate this paragraph and step" command C-c C-p. One solution would be to use ESS instead of the Enhanced Editor. However, I am working on SAS for Windows which does not currently appear to have interactive functionality with ESS.
There is the SUBTOP command which can be used to submit the first n lines of code. However, SUBTOP does not seem to be able to submit code at an arbitrary position within the entire document.
It appears to be SAS standard practice to separate steps by a blank line. This means a block of code may be defined as the text between two non-consecutive blank lines.
I don't know of a direct way to do that. However, there are some useful options.
First off, if you're in the Enhanced Editor, you can use keys to expand/contract code blocks using the Code Folding feature.
Alt + hyphen (Alt -) folds the current block. Then, Shift+(Down Arrow) highlights the whole block (which is now one line), and F8 (or your assigned function key if different) submits that block.
Second, if you use the Program Editor, enable the feature that removes executed code from the window; then you can use SUBTOP effectively.
Third, you might consider structuring your programs differently. If you usually need to run it in pieces, each piece could be a separate program. Enterprise Guide makes this particularly easy to manage; each program gets its own output tab and log, even. One process flow = one 'old' program, with each substantial step being a separate actual program file (however you prefer to run); then you just run by right clicking the step you want to run and selecting submit.
The short answer is no, there is no way to submit a code block in SAS using a single keystroke.
Let me explain why.
A region of text is determined by two aspects of the cursor, point and mark. Point is the current position of the cursor relative to the start of the file. Mark is a variable containing a possible position of the cursor. Region is the text between the point and the mark.
Submitting a code block can be viewed as a two step process:
Select a region.
Submit the selected region to the compiler.
To bind this process to a single key requires being able to select a region using code. The process would go something as follows.
Create a command-style macro which first selects a region, probably
using the FIND command to locate the end of a block (searching for
a carriage return, line feed, "run;" statement, etc.).
Set the mark.
Move the point to the start of the region.
Select the region.
Execute the region using the SUBMIT, GSUBMIT, or END commands.
Compile the macro and bind it to a function key using the KEYS menu.
There are two problems with this.
First, there is no way to set the mark in the Enhanced Editor (EE) using code. Without a mark, a region cannot be defined and the process described above fails. The MARK command referred to by #guest applies only to the Program Editor. To see this, try pressing Ctrl+M or issuing the MARK command from the command line in the EE. You will receive the following message:
ERROR: The MARK command is not supported by the Enhanced Editor.
Second, it is unclear how to select a region using code. The documentation for all of this is disparate and incomplete. Without a way to set the mark, I did not spend too much time investigating how to select.
Tantilizingly, however, is the ability to set the mark in the EE using a keyboard macro. How or why this differs from the MARK command is beyond me. It is also possible to select a region. While a seeming lack of code commands to set mark and select prevents us from creating a single keystroke submit, keyboard macros enable us to develop a two keystoke approach.
Submitting Code
Under Tools > Options > Preferences > Results I have checked "View results as they are generated". This forces the results window to take the foreground after code is submitted.
In the KEYS screen, I have the following:
Key Definition
--- ----------
F3 clear log; end; log; wpgm;
F4 clear log; end;
When I press F3,
the log is cleared (clear log;)
the selected region is submitted (end;)
the log window is selected (log;)
the most recent program window is selected (wpgm;)
This means the results are not immediately displayed to me, depsite the Preferences setting set above. If I want to see the results, I instead press F4. This clears the log and submits the code, but does not select any other windows.
To open the KEYS screen, either type KEYS into the command line in the top left corner of the EE interface or submit dm 'KEYS';. Changes to the KEYS menu must first be saved before they take effect.
Keyboard Macros
For instructions on creating Keyboard Macros.
Select a Single Line of Code
Create a keyboard macro which does the following.
Move cursor to beginning of line
Extend selection to end of line
I have this bound to Ctrl+Enter. I may then execute a line of code using Ctrl+Enter > F3.
Manual Code Selecting/Folding
This approach requires collapsible code sections be enabled. To do this, goto Tools > Options > Enhanced Editor > General and check the 'Collapse code sections' check boxes.
Within the Keyboad Macros,
Assign a command to 'Mark current position' (Ctrl+Space).
Assign 'Toggle expand current line' (Alt+P)
Assign 'Extend selection from mark' (Alt+L)
Once this has been done, place your cursor at the end of a folding block, such as to the right of the semi-colon in a run; statment. Execute the sequence:
Mark current position
Toggle expand current line
Toggle expand current line
Extend selection from mark
A side effect of 'Toggle expand current line' is that when a code block is folded, the point moves to the beginning of the folding block. Since we set the mark at the end of the block, this allows us to define and select a region.
In terms of the keys I have assigned, this is Ctrl+Space > Alt+P > Alt+P > Alt+L. Note that Alt may remain pressed during the last three steps of this sequence so that it becomes Ctrl+Space > Alt (P-P-L). Therefore, to manually submit a folding block using the keyboard, place the cursor at the end of a block and issue Ctrl+Space > Alt (P-P-L) > F3.
Automatic Code Selection/Folding
This automatic process relies on a side-effect of the 'Toggle expand current line' keyboard macro which is described in the previous section. The manual code folding/selecting process is automated using the search function.
The overall process can be seen in two parts:
Find the end of a folding block.
Select the folding block.
Folding blocks are defined by the following.
Beginning of a block:
proc <name/options> ;
data <name/options> ;
%macro <name/options> ;
End of a block:
run;
quit;
%mend;
The semi-colon toggles the block boundary in the EE. The EE naively looks for keyword pairs. So, even though it's nonsense to the compiler, it is possible to define a data-%mend folding block.
The following gives the commands which need to be issued by a keyboard macro for each part.
I. Finding the end-of-block statement
Move cursor to beginning of line (This ensures that the folding block boundary is included in the forward search set in Step 3).
Reset search.
Set search direction to forward.
Set search to case insensitive.
Set search to ignore text in comments.
Set search to code.
Turn on regular expression mode for searching.
Set search to string \<[rqm][ue][ni][dt]*\>;
Find next occurance using the current settings.
Move cursor right (When an end-of-block statement is found, the entire word is highlighted. Moving the cursor to the right places the point at the end of the folding block, to the right of the semi-colon.).
II. Selecting the folding block
Mark current position.
Toggle expand current line. (Folds the section with the side-effect of moving the cursor to the start of the block).
Toggle expand current line. (Unfolds the selection to allow highlighting. The cursor remains at the beginning of the block).
Extend selection to mark.
I have this sequence bound to Ctrl+Shift+Enter.
Note that the search settings altered in the macro do not extend globally. That is, if you hit Ctrl+F and have 'Regular expression search' unchecked, if you again open Ctrl+F after running this macro, you will see that 'Regular expression search' remains unchecked.
Let me explain the regular expression in Step 8 because it is not immediately obvious.
The Ctrl+F dialog does not use Perl Regular Expressions. It uses something else, probably whatever regex syntax came before Perl was integreated into SAS. To see what options are available, click on the arrow beside the "Find text:" text box in the Find dialog. The options we use are given below:
\< matches the beginning of a word
\> matches the end of a word
[] matches a set of characters (via exclusive OR)
* forces 0 or more occurances of the preceeding character(s)
The regular expression \<[rqm][ue][ni][dt]*\>; means that the word must start with r, q, or m. The second character can only be u or e. The third character can only be n or i. If a fourth character exists, it must either be d or t. The last character must be ;. Therefore, only the keywords run;, quit; and mend; will be found. Words containg full or partial matches, such as ammend or treatment, are skipped.
Disadvantages to this approach
Keywords other than run;, quit; and mend; are not supported.
Folding blocks inside folding blocks are not supported. This method is not 'smart' in that it cannot discern which keyword pairs define the outer block.
People who like to put the name of their macro in the mend statement are not supported. Since the regex expression requires a semi-colon at the end, a statement of the form %mend MacroName; will be skipped over.
Based on months of research, this appears to be as complete a solution as can be developed. The lynch pin(s) needed are a code based ability to set mark and to select a region within the Enhanced Editor. If anyone knows of a way to do this, please let others know so that someone may implement the single-key-submit process outlined in the first part of this answer.
How many keystrokes and hand movements does it take in EMACS to identify and submit the code. Do you have to move your right hand off the mouse.
This following will only work in the old text editor
I am pretty sure you can write a command macro but you will need to move the cursor to the start of a paragraph and hit a function key or mouse button
You need to put a macro like the one below on a function key or mouse button
macro
mark;find <empty line> unmark;store;submit past buffer
I can submit a block of code without touching the keyboard very quickly
My right had is usually on the mouse
My index finger is on left mouse button, second finger of right mouse button
highlight code using index finger submit code without moving index finger by
using second finger which is just above the right button.
submit should be on the RMB
I found your solution to this elegant, but I had problems executing the search with you proposed text (I got error). So I changed it
from:
<[rqm][ue][ni][dt]*>;
to:
(?im)run;|quit;|mend;
which seems to do the trick for me.
DW

How do you stop an input/output table from loading and return to the process flow in SAS EG?

SAS can take a very long time to load an output table after you click on it from the process flow, is there a way to cancel it? I've wasted hours waiting for tables to load, I am hoping there is a way to exit the "Input Data" or "Output Data" tabs and return to the process flow window.
I don't know of a way to directly stop the table from loading; in my brief tests, ctrl+break and esc don't stop it, which are the usual possibilities, and both do work in some places in EG. I will say that this is somewhat of a weakness in EG in general; it's not perfect at handling things in the background and allowing you to interrupt, though it's improved greatly over the years.
What you can do to avoid this being a problem, at least possibly, is to go to the Tools->Options->Data->Performance option screen, and limit the Maximum dimensions to display in the data grid value to something well under the default 1,000,000. Change it to 50,000 or something else that is a reasonable compromise between your needs and how long it takes to connect to datasets.
Alternately, you can prevent datasets from appearing on the process flow by altering the option in Tools->Options->Results->Results General Maximum number of output data sets to add to the project to zero. That doesn't prevent you from browsing datasets; you would just have to do it through the Servers tab on the lower left (in the default setup).
If I am not wrong then you would "NOT" want the Input and Output datasets to open when the process is run. Then uncheck the highlighted options in SAS EG, Goto Tools--> Options --> Results --> Results General and uncheck the options shown in image below.

Is there a way to use the SHORT system time picture in C++/MFC?

I have an MFC dialog with a time control. Currently, if I change the 'Long time' format on my PC (for example in Win7 -> Region and Language -> Long time), the dialog will follow suit and display in the selected format. However, I do not need the seconds to be displayed. Is there a way that I can pull the 'Short time' picture instead?
I know that I can remove the seconds by using .SetFormat on the control, but this hard codes whatever format I enter and does not allow the user to switch between standard and military times (which is required).
Use GetLocaleInfoEx to get the format string for the short date (ie LOCALE_SSHORTDATE) for your user's locale setting and pass that to SetFormat method.

What to do if someone tries to add part of a product to a basket?

If a customer were "silly" (being polite here) enough to try and add, as an example, 4.6 items to their basket, what would you expect to see? or how would you deal with it. Obviously, we only deal with digital quantities (our hacksaw broke last week).
There seems to be a lot of inconsistence across the web.
Amazon Rounds down (4.6->4, 1.3->1)
FireBox Rounds (4.6->5, 1.3->1)
Ebuyer ignores the input (no error)
Expansys removes the item from your basket
I'm assuming some site will show an error
Which is the best solution
Add JavaScript verification that would remove non-numeric input while the user is typing in
Implement backward solution for the situation when JavaScript is off, either display an error message or round the value but then display a message saying "your input has been adjusted"
ADDED: Also be aware that the character that separates the fractional part from the integer one differs from country to country. In US I believe it is '.', in Europe it is usually ','. If your applications is targeted at customers in different countries with varying number representation, it would make sense to implement the support for both characters in your application logic. Otherwise some users will get format error messages without knowing why - non-techie people are often unaware of this format issue.
How about validating the user input and accepting only numeric characters?
One solution would be to bring the incorrect input to the user's attention so they can correct it. Rounding can be too much of an assumption depending on the context.
Displaying an error message next to the amount something like this: "I'm sorry, we cannot supply you with 4.6 items. Please enter a whole number." ...or something along those lines.
Another solution would be to avoid displaying error messages by restricting the input field to only allow valid input. ie If you don't want 4.6 items...only allow the user to be able to type 0-9. If the user can't enter incorrect input then there is never any reason to display an error message.
Assuming you're talking about a web app here, you can limit the characters allowed in the input box.
Alternatively, IMO you could use spinner (+/-) controls to change the quantity.
I believe tesco.com does this.
The best solution according to me would be
Customer enters: 4.6
Value changes to 5 after submitting (or if 4.4, round it to 4)
Notice is displayed telling the user that only integers are valid and that the system has roundedy "your" input (4.6) to 5
One solution would be to inform the user that their selection is invalid when they tab off the edit field that's allowed them to enter the fraction.
A lesser option would be to round (down, unless you're greedy to sell 1 extra item), or to reject the input completely.
The best solution is to prevent fractions in the first place by giving them a slider or spin control to select only whole numbers.
At the end it's always safer add server side check.
So if the input it's not an integer value:
I will redirect the user to the same form.
I will set the field with the floor value (4).
I will put on top of the field a message like"This field must be an integer value. May be did you want 4 pieces of this product?"
In my opinion if your product is an shopping system then it makes sense that primary goal is to sell some items. Usually customers want to perform as less actions as possible, so the system should predict what customer could possibly want when typing incorrect inputs.
Amazon Rounds down (4.6->4, 1.3->1) - the best for me, because everything after the decimal point can be destined to some other input;
FireBox Rounds (4.6->5, 1.3->1) - as for me I don't like when someone want to sell me more than I want to buy, so better 'floor' than 'round';
Ebuyer ignores the input (no error) - then you'll sell nothing and user needs to enter some values once again;
Expansys removes the item from your basket - terrible, now I need to search for the item in the shop once again;
I'm assuming some site will show an error. - not bad but required user to retype value;
I would implemented as Amazon plus informing user that input was not fully clear and asking him to recheck the value. So if the system guessed right then user need to change nothing but if he mistyped he'll see it immediately.
Also you could log all this kind of incidents and then perform an analysis, what user typed for the first time and what was the actual count he bought. Just for curiosity...
Well, you definitely should never round up. You should not ever bill for more materials than the customer requested, no matter how inane the request.

multiple CComboBox sharing the same data

I have a MFC dialog with 32 CComboBoxes on it that all have the same data in the listbox. Its taking a while to come up, and it looks like part of the delay is the time I need to spend using InsertString() to add all the data to the 32 controls. How can I subclass CComboBox so that the 32 instances share the same data?
Turn off window redrawing when filling the combos. e.g.:
m_wndCombo.SetRedraw(FALSE);
// Fill combo here
...
m_wndCombo.SetRedraw(TRUE);
m_wndCombo.Invalidate();
This might help.
The first thing I would try is calling "InitStorage" to preallocate the internal memory for the strings.
From MSDN:
// Initialize the storage of the combo box to be 256 strings with
// about 10 characters per string, performance improvement.
int n = pmyComboBox->InitStorage(256, 10);
In addition to what has already been said, you might also turn off sorting in your combo box and presort the data before you insert it.
One way along the lines of your request would be to go owner drawn - you will be writing a fair chunk of code, but you won't have to add the data to all of them.
"CComboBox::DrawItem"
Support.microsoft have this article on subclassing a Combo box which might also be of interest
"How to subclass CListBox and Cedit inside of CComboBox"
Really one has to ask if it is worth the effort, and alot of that depends things like
number of entries in the list
number of times the dialog will show
variability of the combo content
optomising elsewhere
not drawing until the screen is complete
only building the dialog once and re showing it.
using the one combo but showing it in different locations at different times