Get Date from MonthCal Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
Kapitano
Posts: 31
Joined: 07 Sep 2019, 10:58

Get Date from MonthCal

08 Sep 2019, 16:54

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?
Kapitano
Posts: 31
Joined: 07 Sep 2019, 10:58

Re: Get Date from MonthCal

09 Sep 2019, 08:53

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?
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Get Date from MonthCal

09 Sep 2019, 20:06

I think you have to submit the GUI maybe
User avatar
Ragnar
Posts: 611
Joined: 30 Sep 2013, 15:25

Re: Get Date from MonthCal  Topic is solved

10 Sep 2019, 02:00

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
    }
Kapitano
Posts: 31
Joined: 07 Sep 2019, 10:58

Re: Get Date from MonthCal

16 Sep 2019, 12:21

I found another way, which I thought others might find useful.

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()
	}
}
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.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Get Date from MonthCal

24 Oct 2019, 16:16

Here are 2 approaches, although, if you swap the order of approaches 1 and 2, you get an error. If anyone can explain that.

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"))
}
Some relevant documentation info:

Gui Object - Methods & Properties | AutoHotkey v2
https://lexikos.github.io/v2/docs/objects/Gui.htm#OtherOptions
V: 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".
Gui Object - Methods & Properties | AutoHotkey v2
https://lexikos.github.io/v2/docs/objects/Gui.htm#Submit
Collects the values from named controls and composes them into an Object. Optionally hides the window.
GuiControl Object - Methods & Properties | AutoHotkey v2
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
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Get Date from MonthCal

25 Oct 2019, 00:19

@jeeswg, I don't think your approaches would ever be recommended. Edit, I take that back.
if you swap the order of approaches 1 and 2, you get an error. If anyone can explain that.
The docs can, :arrow: Gui.Submit() and :arrow: ControlGetHwnd()

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"))
}
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Get Date from MonthCal

25 Oct 2019, 07:57

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?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Get Date from MonthCal

25 Oct 2019, 08:48

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,

Code: Select all

GetDate.Add("Button", "Default", "Submit").OnEvent("Click", func('ButtonOneClicked').bind(Calendar))
...

ButtonOneClicked(Calendar, *)
{
    MsgBox Calendar.Value
}
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.
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Get Date from MonthCal

25 Oct 2019, 09:06

It just seemed unnecessary since the GUI and GuiControlGet objects provide the same means as long as you name the controls.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Get Date from MonthCal

25 Oct 2019, 09:28

It just seemed unnecessary
Well, it does the necessary job in a very direct and clear way, imo. Control.gui[control] is more roundabout.

Cheers.
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Get Date from MonthCal

25 Oct 2019, 13:31

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
}
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Get Date from MonthCal

26 Oct 2019, 04:05

@Kapitano, hi, creating a GUI in a function and using nested functions and closures as callbacks functions is a very good approach imo :thumbup:, a simpler example,

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
Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Get Date from MonthCal

30 Oct 2019, 20:20

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"]

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
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Get Date from MonthCal

31 Oct 2019, 01:02

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.
Approach 3: Can this be made to work? Ctrl.Gui["SelectDate"]

Code: Select all

;approach 3:
;MsgBox(oCtl.Gui["SelectDate"]) ;doesn't work
Again, read* the documentation, :arrow: 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.

Code: Select all

ButtonOne.OnEvent("Click", "ButtonOneClicked") ;for approaches 1-4
;ButtonOne.OnEvent("Click", (*) => ButtonOneClicked(Calendar)) ;for approaches 1-4 ;equivalent to line above
These lines are not equivalent at all.

Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Get Date from MonthCal

31 Oct 2019, 05:11

- @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.
*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.
- Do you know what 'completely inappropriate' means?
- 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
lexikos
Posts: 9560
Joined: 30 Sep 2013, 04:07
Contact:

Re: Get Date from MonthCal

01 Nov 2019, 07:05

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
Error: This value of type "String" has no property named "Value".
---> xxx: MsgBox(FormatTime(Calendar.Value, "yyyy MM dd"))
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.

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.
If you want working relationships with people, I'd avoid comments like that. Others are 'not as forgiving as I am'.
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.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: Get Date from MonthCal

01 Nov 2019, 07:51

- @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.

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".
You can investigate for yourself why Calendar contains a String rather than the object you expected.
- 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).
- 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
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Get Date from MonthCal

01 Nov 2019, 19:53

jeeswg wrote:
01 Nov 2019, 07:51
And if you'll only listen to me, we can have a better forum.
Wow

Return to “Ask for Help (v2)”

Who is online

Users browsing this forum: songdg, tiska and 35 guests