I created a tree view controls using WinApi. I want to capture mouse click on checkboxes. The notification message NM_CLICK contains NMHDR, which has no information about the node being clicked. since the clicked node may be different from the selected node, there should be a way to find which node has been checked or unchecked, It could be HTREEITEM, or lParam Inserted when adding items to tree view. I want to capture the checking/unchecking in real time. How can I specify which Node being checked/unchecked? any help or link appreciated.
mr.abzadeh
I want to capture the checking/unchecking in real time. How can I
specify which Node being checked/unchecked?
for this exist notification TVN_ITEMCHANGING and TVN_ITEMCHANGED - look for uStateNew and uStateOld members of NMTVITEMCHANGE - when tree view have checkboxes (TVS_CHECKBOXES style) it used as state image list with 2 images - unchecked and checked.
so state & TVIS_STATEIMAGEMASK will be 0 when no checkbox, INDEXTOSTATEIMAGEMASK(1) for unchecked and INDEXTOSTATEIMAGEMASK(2) for checked. based on this info we can and capture mouse click on checkboxes
by using TVN_ITEMCHANGING you can also prevent the change when you return TRUE for this notification. if you need only notify - use TVN_ITEMCHANGED
case WM_NOTIFY:
{
union {
LPARAM lp;
NMTVITEMCHANGE *pnm;
NMHDR* phdr;
};
lp = lParam;
switch (phdr->code)
{
case TVN_ITEMCHANGING:
{
UINT CheckStateOld = pnm->uStateOld & TVIS_STATEIMAGEMASK;
UINT CheckStateNew = pnm->uStateNew & TVIS_STATEIMAGEMASK;
if (CheckStateNew != CheckStateOld)
{
PCSTR szstate = "??";
switch (CheckStateNew)
{
case INDEXTOSTATEIMAGEMASK(1):
szstate = "uncheck";
break;
case INDEXTOSTATEIMAGEMASK(2):
szstate = "check";
break;
}
DbgPrint("%p>%s\n", pnm->lParam, szstate);
}
}
return FALSE;
}
}
also read How to Work With State Image Indexes
// Image 1 in the tree-view check box image list is the unchecked box.
// Image 2 is the checked box.
tvItem.state = INDEXTOSTATEIMAGEMASK((fCheck ? 2 : 1));
notification TVN_ITEMCHANGING and TVN_ITEMCHANGED is available begin from Windows Vista. if you need XP support too - on xp only option use #IInspectable solution
You can send a TVM_HITTEST message (or use the TreeView_HitTest macro) to find the tree view item, given a client-relative coordinate.
To get the cursor position at the time the NM_CLICK message was generated, use the GetMessagePos API.
This allows you do monitor any mouse click in the client area of the control. If you are interested in the state changes as the result of the standard tree view control implementation, you can handle the TVN_ITEMCHANGING or TVN_ITEMCHANGED notifications instead. Both supply an NMTVITEMCHANGE structure, where the hItem identifies the item being changed, and lParam carries application specific data.
Related
What i'm trying to achieve is that when a popup is displayed, the input panel (keyboard) appears as well, and when the user start typing it also update the entry content that is on the panel content.
Unfortunately this appear to be quite complex in Tizen.
What I obtained so far is that the popup is displayed, the kepad too, but when I press buttons on the keypad they are not updating the entry.
In order to start real typing even if the keypad is displayed, i have to tap on the entry.
I did many different tries, without success. The following is the first version of the code and i try to list all the changes i tested:
Evas_Object *popup, *layout;
popup = elm_popup_add(parent);
elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
evas_object_size_hint_weight_set(popup, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_object_part_text_set(popup, "title,text", "Use energy");
layout = elm_layout_add(popup);
elm_layout_theme_set(layout, "layout", "drawer", "panel");
evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
elm_object_content_set(popup, layout);
Evas_Object *entry = elm_entry_add(layout);
set_number_on_entry(entry, 0);
elm_entry_input_panel_layout_set(entry, ELM_INPUT_PANEL_LAYOUT_NUMBERONLY);
elm_entry_input_panel_show(entry);
elm_object_part_content_set(layout, "elm.swallow.content" , entry);
dlog_print(DLOG_INFO, APP_TAG, elm_entry_entry_get(entry));
container->entry = entry;
Evas_Object *button1;
button1 = elm_button_add(popup);
elm_object_text_set(button1, "OK");
elm_object_part_content_set(popup, "button1", button1);
elm_object_style_set(button1, "popup");
evas_object_smart_callback_add(button1, "clicked", ok_pressed_energy, container);
/* Add a "Cancel" button to popup */
button1 = elm_button_add(popup);
elm_object_text_set(button1, "Cancel");
elm_object_part_content_set(popup, "button2", button1);
evas_object_smart_callback_add(button1, "clicked", dismissed_cb, popup);
evas_object_smart_callback_add(popup, "dismissed", dismissed_cb, NULL);
container->popup = popup;
evas_object_show(popup);
elm_object_focus_set(entry, EINA_TRUE);
elm_entry_cursor_end_set(entry);
The first version of the code (the one above) was trying to display the panel while the popup was still creating. So maybe the show call could have impacted on the focus status for the entry.
The following are the changes i tried in order:
I tried to explicitly allow the focus on the entry using:
elm_object_focus_allow_set(entry, EINA_TRUE);
without luck. I also tried to explicitly give the focus to the entry just after the focus allow was set to true, again no success.
I tried to show the panel after the entry was focused (then after the show function for popup was called. Again not working.
Added:
elm_entry_input_panel_enabled_set(entry, EINA_TRUE);
The documentation for that function says:
If true, the input panel is appeared when entry is clicked or has a focus.
Not working
Tried to display the code using the context obtained from the entry with the following code:
Ecore_IMF_Context *imf_context = (Ecore_IMF_Context*)
elm_entry_imf_context_get(entry);
if(imf_context){
dlog_print(DLOG_INFO, APP_TAG , "Imf context");
ecore_imf_context_input_panel_show(imf_context);
}
I tried to post the question also on the Tizen foru, but i still didn't get an answer that solve my problem, this is the link: https://developer.tizen.org/forums/native-application-development/entry-on-popup-focus#comment-27748
What i'm doing wrong? I tried everything but at the moment with no luck. And unfortunately the documentation is not covering this use case (that i think is quite common).
Any help?
I am trying to use Kendo TreeView with other controls. Each of the leaf node on tree opens a detail pane. When I select all the elements from detail pane, I set the state of that node as Checked
myTree.dataItem(node).set("checked", true);
and when all the items are un-selected, I set the state of node as unchecked.
myTree.dataItem(node).set("checked", false);
but if some of the items are selected, I want to show the state of node as Intermediate
how can I do that. I cant find anything in the documentation that can help me. The closest thing I found is
myTree.updateIndeterminate()
however, it is not doing the job. Apparently, it sets the state based on the state of child nodes. but in my case, there are no child nodes. I am dealing with leaf nodes here. Can I set the state of a leaf node as Intermediate ? if yes, how?
Couldn't find any help on this.
Ended up using the following approach
I am now finding the checkbox associated with that particular node and setting it's indeterminate value using jQuery.
function SetTreeNodeIndeterminate(nodeId, set) {
var uid = $("#" + nodeId).parents('li').attr('data-uid');
var node = myTree.findByUid(uid);
if (node.length == 0) return;
var checkBox = $("#_" + uid);
if (checkBox.length == 0) return;
checkBox.prop('indeterminate', set);
updateParentNodeState(node);
}
the following line makes sure that all the parents of a node are also marked as indeterminate
function updateParentNodeState(node) {
myTree.updateIndeterminate(node);
let parentNode = myTree.parent(node);
if (parentNode.length > 0)
updateParentNodeState(parentNode);
}
I am facing an issue where my graph is tree layout and looks fine initially. However, if I choose to change GraphSource upon user input/ clicks using PopulateGraphSource like in the OrgChart example, I get all the nodes stacked on top of each other with no links and all in corner.
I tried resetting graphSource by creating a new one
this.graphSource = new GraphSource();
I also tried to use the Clear method for GraphSource. Neither did solve the problem, I keep having the same issue.
I am using
ObservableCollection<Node> hierarchicalDataSource;
to fill up my GraphSource object.
All I do is create a new one and then call
PopulateGraphSource();
method.
Similar issues: question in telerik support , telerik support different question
Try calling the Layout method on the diagram control. Here is a little fragment of code
TreeLayoutSettings settings = new TreeLayoutSettings()
{
TreeLayoutType = TreeLayoutType.TreeDown,
VerticalSeparation = 60,
HorizontalSeparation=30
};
if (this.diagram.Shapes.Count > 0)
{
settings.Roots.Add(this.diagram.Shapes[0]);
this.diagram.Layout(LayoutType.Tree, settings);
this.diagram.AutoFit();
//this.diagram.Zoom = 1;
}
I'm building an app where the first view has a menu panel, and I want this panel to stick around for the life of the app. The only places the user can "go" are reachable via buttons on this panel (a UICollectionView). In case it matters, this app is landscape-only, and iOS 6-only.
In order to make this work I created a custom segue, which removes everything from the view except for the menu panel, then adds the new view controller's view as a subview, sets the new view's frame to the bounds of the superview, and sends the new view to the back (so it's behind the menu panel). I call viewWill/DidDisappear from prepareForSegue, because otherwise they don't get called.
It may sound kludgy (it does to me), but it works fine except for one thing - the new view comes up from the bottom. It looks funny.
I then tried adding my own animation block - I initially locate the view off to the left, then animate it into place. I send it to the back in the completion block for the animation. This seems perfectly logical, and the frame values are all what they should be. But this one is worse - the view comes in from the lower left corner.
Can anyone suggest a way to make this work? Here's my current perform method:
- (void)perform {
MainMenuViewController *sourceVC = (MainMenuViewController *)self.sourceViewController;
UIViewController *destinationVC = (UIViewController *)self.destinationViewController;
for (UIView *subview in [sourceVC.mainView subviews]) {
// don't remove the menu panel or the tab
if (![subview isKindOfClass:[UICollectionView class]] && [subview.gestureRecognizers count] == 0) {
[subview removeFromSuperview];
}
}
[sourceVC.mainView addSubview:destinationVC.view];
CGRect finalFrame = sourceVC.mainView.bounds;
CGRect frame = finalFrame;
frame.origin.x = finalFrame.origin.x - finalFrame.size.width;
destinationVC.view.frame = frame;
[UIView animateWithDuration:0.5 animations:^{
destinationVC.view.frame = finalFrame;
} completion:^(BOOL finished) {
// make sure it ends up behind the main menu panel
[sourceVC.mainView sendSubviewToBack:destinationVC.view];
}];
}
It turned out to be a simple error - I needed to set destinationVC's frame before calling addSubview. Setting it afterwards was triggering the unwanted animation.
I use an instance of UITextField in which the text is normally aligned to the right, but switches to left alignment when being edited. This is done by calling setTextAlignment: on the editingDidBegin event. Since the update to iOS 6 this behaves strangely: The text alignment is changed correctly from right to left, but the cursor remains at the far right of the text field until some input is performed.
Does anybody know how to restore the expected behaviour so that the cursor moves as well when the alignment is changed?
To give some context: I use the text field to show a value with a unit. The unit is removed during editing and then displayed again after the user hits enter.
Method called on event editingDidBegin:
- (IBAction)textEditingDidBegin:(UITextField *)sender
{
[sender setTextAlignment:NSTextAlignmentLeft];
[sender setText:[NSString stringWithFormat:#"%.0f", width]];
}
Method called on event editingDidEnd:
- (IBAction)textEditingDidEnd:(id)sender
{
[sender setTextAlignment:UITextAlignmentRight];
[sender setText:[NSString stringWithFormat:#"%.0f m", width]];
}
Try resigning the textView as first responder, then make it first responder right after that.
textView.textAlignment = NSTextAlignmentCenter;
[textView resignFirstResponder];
[textView becomeFirstResponder];
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
textField.textAlignment = NSTextAlignmentLeft ;
return YES ;
}
Change the textAlignment before editing did begin. The best place I know to do this is in the UITextFieldDelegate method textFieldShouldBeginEditing.