Hello, new user here. I'm porting my 200+ vTask scripts to AHK v2 (2.0-a104-3e7a9769d), and most of the time it's a great improvement. But one little operation I can't get to work - and all the documentation seems both confusing and out of date.
I want to display a MonthCal dialog, have the user select a date, and when they press Enter, pass the date to a string. Simple, but it's stumped me for days. Could someone post a working script to do this?
Get Date from MonthCal Topic is solved
Re: Get Date from MonthCal
Okay, I've put together a script I don't quite understand, from various online sources.
-----
GetDate := GuiCreate()
Calendar := GetDate.Add("MonthCal", "vSelectDate")
ButtonOne := GetDate.Add("Button", "Default", "Submit").OnEvent("Click", "ButtonOneClicked")
GetDate.Show
ButtonOneClicked(*)
{
MsgBox (FormatTime(String(Calendar.Value), "yyyy MM dd"))
}
-----
...but it only returns today's date. How can it return the selected date?
-----
GetDate := GuiCreate()
Calendar := GetDate.Add("MonthCal", "vSelectDate")
ButtonOne := GetDate.Add("Button", "Default", "Submit").OnEvent("Click", "ButtonOneClicked")
GetDate.Show
ButtonOneClicked(*)
{
MsgBox (FormatTime(String(Calendar.Value), "yyyy MM dd"))
}
-----
...but it only returns today's date. How can it return the selected date?
Re: Get Date from MonthCal
I think you have to submit the GUI maybe
Re: Get Date from MonthCal Topic is solved
The ButtonOneClicked function currently has no access to Calendar. Here are a some examples of how to fix this:
- Declare Calendar as a superglobal variable so that all functions have access to it. For example: global Calendar := GetDate.Add...
- Declare Calendar as a global variable within the desired function. For example: global Calendar
- Use Gui.Submit. For example:
Code: Select all
ButtonOneClicked(Ctrl, *) { Saved := Ctrl.Gui.Submit() ; or GetDate.Submit() if GetDate is declared as superglobal MsgBox Saved.SelectDate }
- Use Gui.__Item. For example:
Code: Select all
ButtonOneClicked(Ctrl, *) { MsgBox Ctrl.Gui["SelectDate"] ; or GetDate["SelectDate"] if GetDate is declared as superglobal }
- Use the fat arrow operator. For example:
Code: Select all
... GetDate.Add("Button", "Default", "Submit").OnEvent("Click", (*) => ButtonOneClicked(Calendar)) ... ButtonOneClicked(Calendar, *) { MsgBox Calendar.Value }
Re: Get Date from MonthCal
I found another way, which I thought others might find useful.
The variable s_DT is a date and time string, defined by the function f_GetDT. In f_GetDT, we create a GUI object called o_GetDT, consisting of a DateTime dialog box, with the value stored in v_SelectDT. When the user changes this value, it triggers the function f_UpdateDT nested inside f_GetDT. f_UpdateDT takes the value in v_SelectDT (passed in s_SelectedDT) and uses it to (re-)define the value of the string s_UpdatedDT. When the user hits Escape, the second nested function f_SubmitDT closes o_GetDT, passing s_UpdatedDT to s_DT.
Elegant? Over-convoluted? An abomination? You tell me.
Code: Select all
s_DT := f_GetDT()
MsgBox (FormatTime(s_DT , "yyyy MM dd, HH:00"))
ExitApp
f_GetDT() {
s_UpdatedDT := a_Now
o_GetDT := GuiCreate("ToolWindow", "Get DT")
o_GetDT.Add("DateTime" , "v_SelectedDT" , "MMMM dd HH:00 yyyy, dddd").OnEvent("Change" , "f_UpdateDT")
o_GetDT.OnEvent("Escape" , "f_SubmitDT")
o_GetDT.Show
WinWaitClose("Get DT")
Return s_UpdatedDT
f_UpdateDT(s_SelectedDT , *) {
s_UpdatedDT := s_SelectedDT.Value
}
f_SubmitDT(*) {
o_GetDT.Destroy()
}
}
Elegant? Over-convoluted? An abomination? You tell me.
Re: Get Date from MonthCal
Here are 2 approaches, although, if you swap the order of approaches 1 and 2, you get an error. If anyone can explain that.
Some relevant documentation info:
Gui Object - Methods & Properties | AutoHotkey v2
https://lexikos.github.io/v2/docs/objects/Gui.htm#OtherOptions
https://lexikos.github.io/v2/docs/objects/Gui.htm#Submit
https://lexikos.github.io/v2/docs/objects/GuiControl.htm#Name
Code: Select all
GetDate := GuiCreate()
Calendar := GetDate.Add("MonthCal", "vSelectDate")
ButtonOne := GetDate.Add("Button", "Default", "Submit").OnEvent("Click", "ButtonOneClicked")
GetDate.Show()
ButtonOneClicked(oCtl, *)
{
;approach 1:
hCtl := ControlGetHwnd("SysMonthCal321", "ahk_id " oCtl.Gui.Hwnd)
Calendar := GuiCtrlFromHwnd(hCtl)
MsgBox(FormatTime(Calendar.Value, "yyyy MM dd"))
;approach 2:
MsgBox(FormatTime(oCtl.Gui.Submit().SelectDate, "yyyy MM dd"))
}
Gui Object - Methods & Properties | AutoHotkey v2
https://lexikos.github.io/v2/docs/objects/Gui.htm#OtherOptions
Gui Object - Methods & Properties | AutoHotkey v2V: Sets the control's Name. Specify the name immediately after the letter V, which is not included in the name. For example, specifying vMyEdit would name the control "MyEdit".
https://lexikos.github.io/v2/docs/objects/Gui.htm#Submit
GuiControl Object - Methods & Properties | AutoHotkey v2Collects the values from named controls and composes them into an Object. Optionally hides the window.
https://lexikos.github.io/v2/docs/objects/GuiControl.htm#Name
The control's name can be used with Gui.__Item to retrieve the GuiControl object. For most input-capable controls, the name is also used by Gui.Submit.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: Get Date from MonthCal
@jeeswg, I don't think your approaches would ever be recommended. Edit, I take that back.
Edit, Another approach, since ButtonOne is object,
The docs can, Gui.Submit() and ControlGetHwnd()if you swap the order of approaches 1 and 2, you get an error. If anyone can explain that.
Edit, Another approach, since ButtonOne is object,
Code: Select all
GetDate := GuiCreate()
Calendar := GetDate.Add("MonthCal", "vSelectDate")
ButtonOne := GetDate.Add("Button", "Default", "Submit")
ButtonOne.OnEvent("Click", "ButtonOneClicked")
ButtonOne.Calendar := Calendar
GetDate.Show
ButtonOneClicked(b,*)
{
MsgBox (FormatTime(String(b.Calendar.Value), "yyyy MM dd"))
}
Re: Get Date from MonthCal
That’s a strange approach. Why would you do that instead of just getting to the calendar reference through the GUI reference in the control object?
Re: Get Date from MonthCal
To get a reference to the calendar via the gui, you have to name it. If I were actually going to to use a calendar and a submit button, I'd probably just bind the calendar to the callback function, example,
That looks similar to Ragnar's last example, but it doesn't rely on an global variable (or a free, if used inside a function).
But I find the property approach simple, and not strange at all.
Cheers.
Code: Select all
GetDate.Add("Button", "Default", "Submit").OnEvent("Click", func('ButtonOneClicked').bind(Calendar))
...
ButtonOneClicked(Calendar, *)
{
MsgBox Calendar.Value
}
But I find the property approach simple, and not strange at all.
Cheers.
Re: Get Date from MonthCal
It just seemed unnecessary since the GUI and GuiControlGet objects provide the same means as long as you name the controls.
Re: Get Date from MonthCal
Well, it does the necessary job in a very direct and clear way, imo. Control.gui[control] is more roundabout.It just seemed unnecessary
Cheers.
Re: Get Date from MonthCal
True. My control event handlers usually look like this:
Code: Select all
GetDate := GuiCreate()
Calendar := GetDate.Add("MonthCal", "vSelectDate")
ButtonOne := GetDate.Add("Button", "Default", "Submit")
ButtonOne.OnEvent("Click", "ButtonOneClicked")
GetDate.Show
ButtonOneClicked(b,*) {
gui := ctrl.gui
.... ; use gui variable from there to reference other controls
}
Re: Get Date from MonthCal
Very good
Re: Get Date from MonthCal
@Kapitano, hi, creating a GUI in a function and using nested functions and closures as callbacks functions is a very good approach imo , a simpler example,
Cheers.
Code: Select all
f() {
GetDate := GuiCreate()
Calendar := GetDate.Add("MonthCal", "vSelectDate")
ButtonOne := GetDate.Add("Button", "Default", "Submit")
ButtonOne.OnEvent("Click", "ButtonOneClicked")
ButtonOneClicked(*) {
msgbox(Calendar.Value)
}
GetDate.Show
}
f
Re: Get Date from MonthCal
The order of approaches in my script above mattered, because the window was being hidden. I needed to set DetectHiddenWindows to On to make it work. (@Helgef: Why did you link to Gui.Submit and ControlGetHwnd?)
Here's an update of my script above:
Approach 1: I probably wouldn't use ControlGetHwnd etc, it's too verbose, however, this was the most intuitive approach, and the quickest to write.
Approach 2: I probably wouldn't use 'Submit', it just seems by nature unintuitive.
Approach 3: I probably wouldn't use the 'v' approach, it just seems by nature unintuitive.
Approach 4: Novel approach, worth considering, in general I had wanted a way to directly link related controls. (Cheers Helgef.)
Approach 5: This and the ControlGetHwnd approach were the first two I had thought of.
Re. Approach 3: Did this ever work? MsgBox Ctrl.Gui["SelectDate"]
Here's an update of my script above:
Approach 1: I probably wouldn't use ControlGetHwnd etc, it's too verbose, however, this was the most intuitive approach, and the quickest to write.
Approach 2: I probably wouldn't use 'Submit', it just seems by nature unintuitive.
Approach 3: I probably wouldn't use the 'v' approach, it just seems by nature unintuitive.
Approach 4: Novel approach, worth considering, in general I had wanted a way to directly link related controls. (Cheers Helgef.)
Approach 5: This and the ControlGetHwnd approach were the first two I had thought of.
Re. Approach 3: Did this ever work? MsgBox Ctrl.Gui["SelectDate"]
Code: Select all
GetDate := GuiCreate()
Calendar := GetDate.Add("MonthCal", "vSelectDate")
ButtonOne := GetDate.Add("Button", "Default", "Submit")
ButtonOne.OnEvent("Click", "ButtonOneClicked") ;for approaches 1-4
;ButtonOne.OnEvent("Click", (*) => ButtonOneClicked(Calendar)) ;for approaches 1-4 ;equivalent to line above
;ButtonOne.OnEvent("Click", Func("ButtonOneClicked2").Bind(Calendar)) ;for approach 5
ButtonOne.Calendar := Calendar ;create property
GetDate.Show()
ButtonOneClicked(oCtl, *)
{
;approach 1:
DetectHiddenWindows("On")
hCtl := ControlGetHwnd("SysMonthCal321", "ahk_id " oCtl.Gui.Hwnd)
Calendar := GuiCtrlFromHwnd(hCtl)
MsgBox(FormatTime(Calendar.Value, "yyyy MM dd"))
;approach 2:
MsgBox(FormatTime(oCtl.Gui.Submit().SelectDate, "yyyy MM dd"))
;approach 3:
MsgBox(FormatTime(oCtl.Gui["SelectDate"].Value, "yyyy MM dd"))
;approach 4: ;create property
MsgBox(FormatTime(oCtl.Calendar.Value, "yyyy MM dd"))
}
ButtonOneClicked2(Calendar, *)
{
;approach 5:
MsgBox(FormatTime(Calendar.Value, "yyyy MM dd"))
}
Last edited by jeeswg on 31 Oct 2019, 05:23, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: Get Date from MonthCal
jeeswg wrote:The order of approaches in my script above mattered, because the window was being hidden. I needed to set DetectHiddenWindows to On to make it work. (@Helgef: Why did you link to Gui.Submit and ControlGetHwnd?)
I linked to these documents so you would read them, if you had, you'd know that gui.submit() hides the window by default and that controlGetHwnd() doesn't detect hidden windows unless you have specified detecthiddenwindows true.
Again, read* the documentation, gui.__item. *Read means to understand the meaning of all the words and symbols written, not just look at it and follow it up with random code tests.Approach 3: Can this be made to work? Ctrl.Gui["SelectDate"]Code: Select all
;approach 3: ;MsgBox(oCtl.Gui["SelectDate"]) ;doesn't work
These lines are not equivalent at all.Code: Select all
ButtonOne.OnEvent("Click", "ButtonOneClicked") ;for approaches 1-4 ;ButtonOne.OnEvent("Click", (*) => ButtonOneClicked(Calendar)) ;for approaches 1-4 ;equivalent to line above
Cheers.
Re: Get Date from MonthCal
- @Helgef: Here's how I might have responded:
- 'You needed DetectHiddenWindows On, which is easily forgotten. Btw Submit hides the window, unintuitive I know. And the error message is unintuitive, but perhaps, for various reasons, it can't be improved.'
- '... Plus you were doing 100 different things at the time, and there were 100 different things that might have gone wrong in the code to consider. Plus AHK v2 alpha regularly changes. Plus you want to conserve your time with the occasional ask for a tip, to be maximally productive and useful to the forum.'
- I would have avoided the DetectHiddenWindows problem by using 'ahk_opt VH', had it been implemented, to always check both visible and hidden windows. But when I posted about this, you responded unconstructively with an emoji, so you held back a chance to finalise some important functionality.
- If you want working relationships with people, I'd avoid comments like that. Others are 'not as forgiving as I am'.
- Re. Gui.__Item, I literally copied that from someone else's example, and it didn't work.
- So you could respond: 'no, that never worked, try this ...' (add .Value), or, 'it used to work, but it was changed like so ...'.
- 'equivalent to line above' is essentially true. 'These lines are not equivalent at all' is false. You could suggest a rephrasing.
- In short, you could have mentioned DetectHiddenWindows, explained re. Gui.__Item, proposed a rephrasing, responded sensibly re. ahk_opt, not given some ridiculous 'lecture' about what 'reading' means, and respected my judgement about asking for a tip.
- 'You needed DetectHiddenWindows On, which is easily forgotten. Btw Submit hides the window, unintuitive I know. And the error message is unintuitive, but perhaps, for various reasons, it can't be improved.'
- '... Plus you were doing 100 different things at the time, and there were 100 different things that might have gone wrong in the code to consider. Plus AHK v2 alpha regularly changes. Plus you want to conserve your time with the occasional ask for a tip, to be maximally productive and useful to the forum.'
- I would have avoided the DetectHiddenWindows problem by using 'ahk_opt VH', had it been implemented, to always check both visible and hidden windows. But when I posted about this, you responded unconstructively with an emoji, so you held back a chance to finalise some important functionality.
- Do you know what 'completely inappropriate' means?*Read means to understand the meaning of all the words and symbols written, not just look at it and follow it up with random code tests.
- If you want working relationships with people, I'd avoid comments like that. Others are 'not as forgiving as I am'.
- Re. Gui.__Item, I literally copied that from someone else's example, and it didn't work.
- So you could respond: 'no, that never worked, try this ...' (add .Value), or, 'it used to work, but it was changed like so ...'.
- 'equivalent to line above' is essentially true. 'These lines are not equivalent at all' is false. You could suggest a rephrasing.
- In short, you could have mentioned DetectHiddenWindows, explained re. Gui.__Item, proposed a rephrasing, responded sensibly re. ahk_opt, not given some ridiculous 'lecture' about what 'reading' means, and respected my judgement about asking for a tip.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: Get Date from MonthCal
What normally happens when you submit a form? The form closes, the browser navigates you away from the form, or for a paper form, you don't have possession of it anymore. This is where the Submit method/sub-command gets its name. It is intuitive for the GUI to hide.
The error message (when putting your approach 2 before approach 1 in ButtonOneClicked), which should be
Maybe you were using an outdated alpha, and received "No object to invoke." In this case, it should still be clear that Calendar does not contain an object, and it shouldn't take long to figure out why.
@jeeswg, to be maximally productive and useful to the forum, you should think and read more and post less.
My opinion is that your posts are very abrasive, and even putting aside format, that they lower the overall quality of the forum. I know others share this opinion, and some have expressed real concern about the overall quality of the forum's content due to the volume of your posts.
The error message (when putting your approach 2 before approach 1 in ButtonOneClicked), which should be
IMO has no room for improvement, except perhaps to show that Calendar is an empty string. You are attempting to retrieve the property Value of the string Calendar, and it has no such property. It could try to tell you the name of the variable which the value came from, but in this case there's only one attempt to read the Value property on this line, so it should be obvious. You can investigate for yourself why Calendar contains a String rather than the object you expected.Error: This value of type "String" has no property named "Value".
---> xxx: MsgBox(FormatTime(Calendar.Value, "yyyy MM dd"))
Maybe you were using an outdated alpha, and received "No object to invoke." In this case, it should still be clear that Calendar does not contain an object, and it shouldn't take long to figure out why.
@jeeswg, to be maximally productive and useful to the forum, you should think and read more and post less.
My opinion is that your posts are very abrasive, and even putting aside format, that they lower the overall quality of the forum. I know others share this opinion, and some have expressed real concern about the overall quality of the forum's content due to the volume of your posts.
You are not in a position to give others advice on how to communicate, or maintain working relationships, on this forum. The condescending or hostile posts directed at you are not merely due to some flaw of the person making them, but directly caused by the way you communicate and what you post. "Lecturing" Helgef will not help Helgef, or you, or anyone else, regardless of who is right or wrong. It will just generate more noise and perhaps animosity.If you want working relationships with people, I'd avoid comments like that. Others are 'not as forgiving as I am'.
Re: Get Date from MonthCal
- @lexikos: As a user when you 'submit', you expect a change/notification, not necessarily hiding. As a programmer, you don't necessarily expect the variable collection *and* hiding to be coupled.
- Re. the error message. This is unintuitive, because arguably 'var1' doesn't have any type, it's undefined. Also, it doesn't indicate which variable has the problem. Also, the use of 'value' is potentially confusing, arguably it doesn't have a value, it's undefined.
- I deliberately give people key tips to save them time.
- Btw the GUI and object documentations are lengthy/complex/incomplete/changing, if I say can someone give me a tip, so that I complete a task that night and not a week/month later, I'm right to do so, and I don't expect some child to say 'you don't know how to read' or whatever ludicrous/abrasive/inappropriate/unacceptable statement they come up with.
- And if I respond (reasonably politely) to that, to try and immediately end/prevent that kind of time-wasting/noise/distraction/spam, I'm right to do so.
- Anyone is in a position to give anyone advice. I am in a position to give you advice, and vice versa, it is reciprocal. For example: some people regard you as unduly abrasive at times, and this makes them reluctant to message you in threads. For example: one good point about Chris is that he tried quite hard to make people feel welcome.
- The 3 users I can think of, who have been mildly condescending towards me, have also been equally condescending towards you. Is it your fault that you were condescended to?
- Thanks for appreciating my half-dozen contributions to the forum, including to the key updates: AHK v1.1.27/1.1.28/1.1.29, and some AHK v2 updates.
- What is most lowering the quality of the forum, is that the AHK v1 code being written now is already out-of-date. The aim of being able to write forwards compatible code in AHK v1 should be paramount, if forum quality is your main concern. My Wish List 2.0 covers the details.
- It's a trait that abrasive people view others as abrasive, I could name 3 to 6 people on this forum like that. In general you find a large cohort of IT types don't understand others, I think it explains a lot of the problems in the industry, that are on a much smaller scale elsewhere.
- I have had *a lot* of support from people re. dealing with the likes of you lot. And if you'll only listen to me, we can have a better forum. The fundamental point is, don't go about insulting people/belittling people, this is something I always avoid.
- Re. the error message. This is unintuitive, because arguably 'var1' doesn't have any type, it's undefined. Also, it doesn't indicate which variable has the problem. Also, the use of 'value' is potentially confusing, arguably it doesn't have a value, it's undefined.
Code: Select all
MsgBox(var1.myprop " " var2.myprop " " "abc".myprop)
;Error: This value of type "String" has no property named "myprop".
;this is arguably more intuitive:
;Error: A variable (or literal string) has no property named "myprop".
;or even:
;Error: A value has no property named "myprop".
- No, this is completely wrong, I'd rather not waste my life investigating curios when people already know the answer. It's only so often that I can do a full read-through of the AHK v2 object documentation pages. Plus *other people* may want to know the answer, plus re-explaining it might add clarity/information not present in the documentation (that might end up in a revised version of the documentation).You can investigate for yourself why Calendar contains a String rather than the object you expected.
- I deliberately give people key tips to save them time.
- Btw the GUI and object documentations are lengthy/complex/incomplete/changing, if I say can someone give me a tip, so that I complete a task that night and not a week/month later, I'm right to do so, and I don't expect some child to say 'you don't know how to read' or whatever ludicrous/abrasive/inappropriate/unacceptable statement they come up with.
- And if I respond (reasonably politely) to that, to try and immediately end/prevent that kind of time-wasting/noise/distraction/spam, I'm right to do so.
- Anyone is in a position to give anyone advice. I am in a position to give you advice, and vice versa, it is reciprocal. For example: some people regard you as unduly abrasive at times, and this makes them reluctant to message you in threads. For example: one good point about Chris is that he tried quite hard to make people feel welcome.
- The 3 users I can think of, who have been mildly condescending towards me, have also been equally condescending towards you. Is it your fault that you were condescended to?
- Thanks for appreciating my half-dozen contributions to the forum, including to the key updates: AHK v1.1.27/1.1.28/1.1.29, and some AHK v2 updates.
- What is most lowering the quality of the forum, is that the AHK v1 code being written now is already out-of-date. The aim of being able to write forwards compatible code in AHK v1 should be paramount, if forum quality is your main concern. My Wish List 2.0 covers the details.
- It's a trait that abrasive people view others as abrasive, I could name 3 to 6 people on this forum like that. In general you find a large cohort of IT types don't understand others, I think it explains a lot of the problems in the industry, that are on a much smaller scale elsewhere.
- I have had *a lot* of support from people re. dealing with the likes of you lot. And if you'll only listen to me, we can have a better forum. The fundamental point is, don't go about insulting people/belittling people, this is something I always avoid.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Who is online
Users browsing this forum: dijek and 68 guests