Say I want to access a specific view in a doc class in MFC MDI application if it is already opened. The view can be currently active or not. If I can assume the view is always active, I can follow this instruction
http://support.microsoft.com/kb/108587
but the view can be also non-active. Is there any way to do this?
There shorter ways to do this, but here's the straight up way. Assume the following code is a menu handler in your CMainFrame class:
for( POSITION pos = AfxGetApp()->GetFirstDocTemplatePosition(); pos != NULL; )
{
CDocTemplate* pTempl = AfxGetApp()->GetNextDocTemplate( pos );
for( POSITION pos1 = pTempl->GetFirstDocPosition(); pos1!= NULL; )
{
CDocument* pDoc = pTempl->GetNextDoc( pos1 );
for( POSITION pos2 = pDoc->GetFirstViewPosition(); pos2 != NULL; )
{
CView* pView = pDoc->GetNextView( pos2 );
if( pView->IsKindOf( RUNTIME_CLASS(...) ) )
{
// Do what you need with the view...
}
}
}
}
You basically have to get a pointer to the Template, look at the CDocuments associated with it, and for each CDocument, traverse through all the views attached to the document.
If you only use one template, one document, and multiple views attached, you can save the template in CMainFrame class and get to it faster by calling AfxGetApp()->m_pTemplate.
MFC is funky in some ways, but it lets you get to any part of the Doc/View architecture if you needed.
Hope this points you in the right direction.
Related
I currently face the following problem:
I have 64 labels. Label_1 all the way up to Label_64.
I also have an int i.
"i" also goes from 1-64
I want that, when i == 1 Label_1 shall display an image. If i == 2, Label_2 shall display that image and so on.
Currently I'd do that with:
if(i == 1)
{
QPixmap pix("...");
ui->label_1->setPixmap(pix);
}
if(i == 2)
{
QPixmap pix("...");
ui->label_2->setPixmap(pix);
}
if(i == 3)
{
QPixmap pix("...");
ui->label_3->setPixmap(pix);
}
...
Is there some way to do that easier? Something like:
QPixmap pix("...");
ui->label_i->setPixmap(pix);
where the choosen label is directly defined by i?
You can store a list of QLabels.
QList<QLabel*> labels;
labels.at(i)->setPixmap(pix)
The disadvantage of this method is that you should manually assign ui->label_i to labels.at(i) for every i from 1 to 64 once:
labels.insert(0, NULL); // empty space to keep numbering the same.
labels.insert(1, ui->labels_1);
labels.insert(2, ui->labels_2);
...
labels.insert(64, ui->labels_64);
Depending on your specific case, you may use a more tricky solution. For example, if all the labels are stored in a QVBoxLayout at position 1 to 64, you can access label i as follows:
QVBoxLayout *layout = ...;
QLabel *label = qobject_cast<QWidget*> (layout->itemAt(i)->widget ());
if (label) // should be true if assumption is correct
label->setPixmap(pix);
You can also use method two to initialise the list of method 1.
See the Qt documentation for more information.
When the player approaches an item I want some of it's properties to be displayed, but I don't want that info to cover up the player. I have the following code which does not work.
t = GetComponentInChildren<Text> ();
void OnTriggerEnter(Collider col){
if (col.gameObject.tag.Equals ("Player")) {
playerInRange = true;
col.GetComponent<Controller>().itemsInRange.Add(this.gameObject);
GetComponentInChildren<Canvas> ().enabled = true;
}
if (player.transform.position.x < this.transform.position.x) {
Debug.Log ("On yer right!");
t.rectTransform.position.Set(this.transform.position.x+50, this.transform.position.z, this.transform.position.z);
}
if (player.transform.position.x > this.transform.position.x) {
t.rectTransform.position.Set(this.transform.position.x-50, this.transform.position.z, this.transform.position.z);
}
}
The Debug.Log shows up, so all conditions are being met, but the text is not moving. Anyone have any ideas?
The issue is that the getter for tranform.position returns a 'copy' of the position Vector3, so calling Set will only change the 'copy' of that vector3 and not the position of the rect transform.
This is because Vector3 is a struct and not a class and therefore isnt passed via reference. https://msdn.microsoft.com/en-us/library/ms173109.aspx
so instead of calling set i would assign a new vector 3 to the position variable
t.rectTransform.position = new Vector3(transform.position.x-50, transform.position.y, transform.position.z);
If you're hitting the debug, can you verify the position you are displaying is where you expect it to be, currently the second and third parameters to the 'Set' method is:
this.transform.position.z
Wouldn't the middle one be expected to be position.y?
I already managed to create wxListCtrls with either icons or multicolumn text like this
Picture of two wxListCtrls
Now I'd like to add an icon to each line of the text list on the left. I thought this should be possible as typical wxWidgets applications like code::blocks and wxSmith often diplay icons in list/tree views (resource browser window) and even in tabs of notebooks (compiler log window).
So how can I create something like this? (Everybody knows Windows Explorer)
Picture of Explorer Window with icons
I tried this...
SetImageList (ToolImages, wxIMAGE_LIST_NORMAL);
InsertColumn (0, "Icon");
SetColumnWidth (0, 40);
...
for (int i=0; i<5; i++)
{
InsertItem (i, i);
SetItemColumnImage (i, 0, i);
SetItem (i, 1, IntToStr (i+1));
...
But as you can see, only the text gets displayd, the image column is blank. Is it possible at all to mix text and images in report mode? If not, what other wxControl class can I use to get the desired result?
Many Thanks in advance.
Yes, it is possible, and the listctrl sample shows how to do it, in particular see MyFrame::InitWithReportItems() function. The only difference with your code seems to be that you use a different InsertItem() overload, so perhaps you should use InsertItem(i, "") instead.
Also check that your image list does have the 5 icons in it.
More generally, trying to reduce the differences between your code and the (working) sample will almost always quickly find the problem.
Thanks, VZ, but I found out that it's not the InsertItem() but the SetImageList(). My image list was correct, but the "which" parameter wasn't. Replacing wxIMAGE_LIST_NORMAL by wxIMAGE_LIST_SMALL fixes the problem! I thought "SMALL" was only meant for the SMALL_ICON mode and that "NORMAL" should be the default. But yes, that makes sense, normal icons are big and don't fit in the text display. Would be nice if the documentation had told us that before long trial and error...
This is a simple example for SMALL ICONIC VIEW USING WXLISTCTRL .Please place this code inside the class declaration.I did it in Frame based Windows Application using CODE BLOCKS.It will be useful to you.
wxImageList *il=new wxImageList(32,32,false,0);
wxImageList *i2=new wxImageList(32,32,false,0);
wxDir dir(wxGetCwd());
wxDir dir1(wxGetCwd());
if ( !dir.IsOpened() )
{
// deal with the error here - wxDir would already log an error message
// explaining the exact reason of the failure
return;
}
if ( !dir1.IsOpened() )
{
// deal with the error here - wxDir would already log an error message
// explaining the exact reason of the failure
return;
}
puts("Enumerating object files in current directory:");
wxString path, filename, dirstring,filename1, dirstring1, img,imgPath,path1,img1,imgPath1;
int i=0;
path=wxT("C:\\testing\\splitterwindow\\set\\devices");
path1=wxT("C:\\testing\\splitterwindow\\set\\actions");
img=wxT("C:\\testing\\splitterwindow\\set\\devices\\");
img1=wxT("C:\\testing\\splitterwindow\\set\\actions\\");
bool cont=dir.Open(path);
bool cont1=dir1.Open(path1);
cont = dir.GetFirst(&filename, wxEmptyString, wxDIR_DEFAULT);
dirstring.Append(filename.c_str());
cont1 = dir1.GetFirst(&filename1, wxEmptyString, wxDIR_DEFAULT);
dirstring1.Append(filename1.c_str());
while ( cont )
{
imgPath.clear();
cont = dir.GetNext(&filename);
dirstring.Append(filename.c_str());
// Consturct the imagepath
imgPath.Append(img.c_str());
imgPath.Append(filename.c_str());
//Now, add the images to the imagelist
il->Add(wxBitmap(wxImage(imgPath.c_str())));
i++;
}
while ( cont1 )
{
imgPath1.clear();
cont1 = dir1.GetNext(&filename1);
dirstring1.Append(filename1.c_str());
// Consturct the imagepath
imgPath1.Append(img1.c_str());
imgPath1.Append(filename1.c_str());
//Now, add the images to the imagelist
i2->Add(wxBitmap(wxImage(imgPath1.c_str())));
i++;
}
//assigning the imagelist to listctrl
ListCtrl1->AssignImageList(il, wxIMAGE_LIST_SMALL);
ListCtrl3->AssignImageList(i2, wxIMAGE_LIST_SMALL);
for(int j=0;j < il->GetImageCount()-1;j++)
{
wxListItem itemCol;
itemCol.SetId(j);
itemCol.SetImage(j);
itemCol.SetAlign(wxLIST_FORMAT_LEFT);
ListCtrl1->InsertItem(itemCol);
}
for(int k=0;k < i2->GetImageCount()-1;k++)
{
wxListItem itemCol1;
itemCol1.SetId(k);
itemCol1.SetImage(k);
itemCol1.SetAlign(wxLIST_FORMAT_LEFT);
ListCtrl3->InsertItem(itemCol1);
}
`
At the moment i have the following problem, i'm applying span tags with the applyStyle Method from CKEDITOR 4.x. But when a span is partial selected and i execute the applyStyle method a new span will be made with the selection, but the other half of the selected span isn't restored and loses his span.
First Question: Is it possible to prevent partial selection of a certain element?
IF NOT My Second Question: Is it possible to extend the Selection only on one side, the side where the span(With a certain class or attribute) is partial selected. So that it will be fully selected for processing.
A Example:
This is 'my text <span class"testClass">, This' is </span> Other Text
And now we want a solution to create:
This is <span class"testClass2"> my text, This</span> <span class"testClass"> is </span> Other Text
Please take notice of the following:
The hard part in this is to maintain the html structure. when half of the selection is in an other block level element, it may not brake! That is the reason that i started using the applyStyle method.
First Question: Is it possible to prevent partial selection of a certain element?
Hmm... You can check placeholder plugin's sample - it uses non-editable inline elements to create those placeholders which at least on Chrome cannot be partially selected. Though, I think it's not a satisfying solution for you :)
Another possible solution is using editor#selectionChange event on which you can check if one of selection ends is located inside that element and if yes, set it before or after that element. It'd look like (I haven't tested this code, it's just a proto):
editor.on( 'selectionChange', function( evt ) {
var sel = evt.data.selection,
range = sel.getRanges()[ 0 ];
if ( protectedElement.contains( range.startContainer ) || protectedElement.equals( range.startContainer ) )
range.setStartAt( protectedElement, CKEDITOR.POSITION_BEFORE_START );
if ( protectedElement.contains( range.endContainer ) || protectedElement.equals( range.endContainer ) )
range.setEndAt( protectedElement, CKEDITOR.POSITION_AFTER_END );
sel.selectRanges( [ range ] );
} );
Although, this kind of solutions are always dangerous and can cause many unpredictable situations. But it may be worth checking it.
Back to the root of your problem - I understand that you want to create styles which work on the same level - i.e. only one can be applied in one place. This isn't possible using styling system. You would have to prepare range before applying style. The code would be similar to the selectionChange listener - you check if ends are anchored in style element, if yes you need to move range's ends out of it. The only question is how to exclude entire element from range in this situation:
<p>foo[bar<span class="st1">bom</span>bim]foo</p>
The result should be two ranges:
<p>foo[bar]<span class="st1">bom</span>[bim]foo</p>
Unfortunately current range's API does not include helpful method like range#exclude, therefore you need to implement yours. I would try doing this with walker. Iterate from range's start to end and remember all style elements. If you'll do this in both directions you'll gather also partially selected elements on both ends, so the first step I described will be unnecessary. When you'll have list of elements which you want to exclude from range, then you just need to create ranges at both ends and between these elements - this part should be easy. Element#getPosition will be helpful, but you'll need to check its code to understand how to use it because it isn't documented.
I have been looking and trying for hours. And chose to make an enlarge function myself to expand the selection. I made my own enlarge/expand function as i wanted to have more control which the enlarge of CKEDITOR doesn't provide.
The code:
//Vars
var firstNode = range.startContainer.getParent();
var lastNode = range.endContainer.getParent();
//Make end Get full if is tcElement
if(lastNode.type === CKEDITOR.NODE_ELEMENT && lastNode.getName() === "myElement")
{
range.setEndAfter(lastNode);
}
//Make end Get full if is tcElement
if(firstNode.type === CKEDITOR.NODE_ELEMENT && firstNode.getName() === "myElement")
{
range.setStartBefore(firstNode);
}
range.select();
Other nice piece of code, which isn't very hard but can be useful for other people.
This code i used to split the code in 2 or 3 parts.. where part 1 and 3 are the partial selection if existed.
Spliting to multiple ranges
//Vars
var newRanges = [];
var allWithinRangeParent = range.getCommonAncestor().getChildren();
var firstNode = range.startContainer;
var lastNode = range.endContainer;
var firstNodeStart = range.startOffset;
var lastNodeEnd = range.endOffset;
//TODO make if to check if this needs to be made.
//make end partial
var newEndRange = new CKEDITOR.dom.range( editor.document );
newEndRange.selectNodeContents( lastNode );
newEndRange.endOffset = lastNodeEnd;
newRanges.push(newEndRange);
//TODO make if to check if this needs to be made.
//Make start partial
var newStartRange = new CKEDITOR.dom.range( editor.document );
newStartRange.selectNodeContents( firstNode );
newStartRange.startOffset = firstNodeStart;
newRanges.push(newStartRange);
//Make center selection.
var tempRange = new CKEDITOR.dom.range( editor.document );
tempRange.setStartBefore(firstNode.getParent().getNext());
tempRange.setEndAfter(lastNode.getParent().getPrevious());
newRanges.push(tempRange);
selection.selectRanges(newRanges);
I tried some different ways do find rows in a table where a columns contain a particular link.
My goal: replace an icon when a link to xyz is in this same row as the image.
This is my snippet so far:
var rows = document.getElementsByTagName("tr");
for(var i = rows.length - 1; i >= 0; i--) {
var links = rows[i].getElementsByTagName("a");
for(var k = links.length - k; k >= 0; k--) {
if (links[k].href =="http://www.XXXX.net/forum/index.php?showforum=121"){
var images = rows[i].getElementsByTagName("img");
for (var j=0;j<images.length;j++) {
images[j].src = "http://www.XXXX.net/forum/folder_post_icons/icon7.gif";
}
}
}
}
I'm pretty sure this is not really the best concept. But as you might see I try to search links in all rows and once the link to forum "121" is found, I try to replace all images in this particular row.
What I get is every image at the site getting replaced.
Since it's simple enough, here's a complete script that does that.
It uses jQuery and here's a handy jQuery reference. See, especially, the Selectors section (which are almost the same as CSS Selectors).
Re: "What I get is every image at the site getting replaced." ...
This maybe because the search criteria is too broad. If it's a poorly designed (uses table layouts) page, every image may be in a table row with a target link!
When posting Greasemonkey questions, link to the target page, or at the very minimum, post enough of the page's HTML that we can adjust the GM script to match.
Anyway, this will work, possibly pending more information about the target page:
// ==UserScript==
// #name _Replace image on custom-targeted row
// #include http://www.XXXX.net/forum/*
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
// ==/UserScript==
//--- This may need tuning based on information not provided!
var targetLinks = $("tr a[href*='showforum=121']");
//--- Loop through the links and rewrite images that are in the same row.
targetLinks.each ( function () {
//--- This next assumes that the link is a direct child of tr > td.
var thisRow = $(this).parent ().parent ();
//--- This may need tuning based on information not provided!
var images = thisRow.find ("td img");
//--- Replace all target images in the current row.
images.each ( function () {
$(this).attr (
'src',
'http://www.XXXX.net/forum/folder_post_icons/icon7.gif'
);
} );
} );