I have an MFC SDI application to display a list of data read from a csv file. So I set up its view to be inherited from CListView and make it a virtual list control. That means I have to use LVS_OWNERDATA as one of its CListCtrl style attributes. Yet I now run into a problem when I have to include Checkboxes in each row of the displayed list. As you might know, LVS_EX_CHECKBOXES can't be used with LVS_OWNERDATA, I therefore create a bitmap file to contain 2 small images of checkbox (selected and de-selected) and toggle them every time the user clicks on the loaded image/icon. I am handling this in OnNMClick method. And I have two problems I would like to ask for your help to solve.
(1) I don't know how to update the virtual list (which is commonly handled in OnLvnGetdispinfo method) so I try this in OnNMClick and find that the check and unchecked images aren't toggled.
void CMFCSDITest::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: Add your control notification handler code here
*pResult = 0;
LVHITTESTINFO hitinfo;
hitinfo.pt = pNMItemActivate->ptAction;
int nItem = pListCtrl->HitTest(&hitinfo);
if (hitinfo.flags != LVHT_ONITEMICON)
return;
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
LV_ITEM* pItem = &(pDispInfo)->item;
if (pItem->iImage == 0)
pItem->iImage = 1;
else
pItem->iImage = 0;
pListCtrl->SetItem(pItem);
pListCtrl->UpdateWindow(); //this is wrong as nothing seems updated after all.
}
Given that the created imagelist is inserted into the pListCtrl already (in OnInitialUpdate method) and I set the output image index value in OnLvnGetdispinfo method.
(2) Instead of handling OnNMClick, I read somewhere people's advice that OnLvnItemchanged method could also be used. However in LPNMLISTVIEW struct, there is uNewState and uOldState variable members for which I don't know how to set up my tiny checked and unchecked icons as status images. Because I might have to do this
if (pNMLV->uChanged & LVIF_STATE)
{
switch (pNMLV->uNewState & LVIS_STATEIMAGEMASK)
{
case image1://do
case image2://do
}
}
Related
I have this script that finds a paragraph style, puts an item from a library at the very end and applies object style:
myDoc = app.documents[0];
myLib = app.libraries[0];
myObjectStyle = myDoc.objectStyles.item ("marker");
app.findTextPreferences = app.changeTextPreferences = null;
app.findTextPreferences.appliedParagraphStyle = "Custom"
var myFound = app.activeDocument.findText(true);
alert (myFound.length);
try {
for (i = 0; i < myFound.length; i++) {
myIcon = myLib.assets.itemByName("winieta_tr").placeAsset (myFound[i].insertionPoints[-2])[0];
myIcon.appliedObjectStyle = myObjectStyle;
// myFound[i].remove ();
}
}
catch (e) {alert (e.message)}
I don't know how to alter it, so the items are obtained not from library but form pasteboard - any help would be appreciated.
Is it possible to find elements that are in the document by name, as it is with library elements?
Yes, you can find an object by name (you would assign that name in the layers panel) simply by using
myDoc.pageItems.itemByName("myItemName");
If you are looking for the same thing on a specific spread (for example if several items on several spreads have the same name), you can use
myDoc.spreads[0].pageItems.itemByName("myItemName");
Or if you just want to use the currently active spread
app.activeWindow.activeSpread.pageItems.itemByName("myItemName");
Just make sure not to use the page to address a page item on the pasteboard as the pasteboard does not belong to any page.
Is it possible to find elements that are in the document by name, as it is with library elements?
You can apply a script labels to the frame on the pasteboard to give it a name.
I'm trying to use extension for Qlikview 11SR2.
I've tried to access data with this.Data.Rows, but this object is empty even though the data is not empty and I can display the data in a table.
The code I have used is:
var obj = this.Data;
for(var prop in obj) {
var div = document.createElement("div");
div.innerHTML = "" + prop + "" + obj[prop];
this.Element.appendChild(div);
}
I have no access to the internet - I work offline.
How can i make this.Data.Rows contain the data (it is undefined)?
Based on your feedback, I would say it might be worth trying a slightly different way of accessing your data as the this.Data.Rows object contains a collection of row objects which in turn contain one or more objects, which relate to the dimensions and measures passed to the script (and are defined in definition.xml).
For example, say that I have an extension that features a dimension and a measure (in that order). I can access each value of these in a loop as follows:
for (var rowIx = 0; rowIx < this.Data.Rows.length; rowIx++) {
var row = this.Data.Rows[rowIx];
myDimensionValue = row[0].text;
myMeasureValue = row[1].text;
}
I can then add code to output each value of myDimension and myMeasureValue to the loop, such as in your case adding a new div for each set of values.
I found the "QVConsole" extension invaluable when writing extensions, as it allows you to have a JavaScript console in your QlikView document, so you may then use statements like console.log(myDimensionValue) etc. to help you debug your extension. You can download it from https://github.com/thomasfriebel/QvConsole.
In you extension object in the webview, set the dimension and a valid expression. Let me know whether it works!
I'm trying to use two devExpress checkedComboBoxes (boxes) to maintain a list and its antilist (i.e, same items in both comboboxes, and they must be checked in only one of the lists).
I'm using C++/CLI, so for each box I handle
EditValueChanged += gcnew System::EventHandler(this, &SelectionControl::exclBox_EditValueChanged);
which calls through to
void
box_ToggleAntibox(
DevExpress::XtraEditors::CheckedComboBoxEdit^ box,
DevExpress::XtraEditors::CheckedComboBoxEdit^ antibox )
{
using namespace DevExpress::XtraEditors::Controls ;
cli::array<String ^> ^ sAnti = gcnew cli::array<String ^>(2*box->Properties->Items->Count) ;
int ii = 0;
String ^ delim = ", ";
for each (CheckedListBoxItem^ i in box->Properties->GetItems()) {
if (i->CheckState==Windows::Forms::CheckState::Unchecked)
{
sAnti[ii] = i->Value->ToString();
++ii;
sAnti[ii] = delim;
++ii;
}
}
String ^ result = String::Concat(sAnti);
antibox->EditValue = result;
}
As the devExpress documentation seems to say to set the edit value, rather than simply iterating through the box list and setting the anti-list to !Checked.
However, it doesn't seem to be working (the correct items are added to the text window, but nothing is checked). Moreover, if I look at my box after the event has finished, I find that the string value in the text window is correct (reflects what I'd selected), but if I open it up, then all items are selected.
Does anyone have any suggestions I might try?
Is it better to set each item's CheckState::Checked instead?
Thanks!
I spent some time talking to DevExpress support. The short answer is that this should work - but doesn't for us. Your mileage may vary, but our solution was to put the two comboboxes on to separate controls on the form.
Hey guys, I'm trying to make a 2D Platform style game similar to this game below:
http://www.gameshed.com/Puzzle-Games/Blockdude/play.html
I have finished making most of the graphic, and areas, and collision, but our character is still not able to carry things. I'm confused as to what code to use so that my character can carry the blocks. I need help as to how to make our character carry blocks that are in front of him, provided that the blocks that don't have anything on top of it. This has been confusing me for a week now, and any help would be highly appreciated. :D
I fondly remember my first AS2 game. The best approach is probably an object oriented approach, as I will explain.
In AS2, there is a hittest method automatically built into objects. There is a good tutorial on Kirupa here:
http://www.kirupa.com/developer/actionscript/hittest.htm
also
http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001314.html
First you'll want to generate your boxes using a Box class. Your class would need to look something like the following:
//Box.as pseudo-code
class Box {
var x_pos:Number;
var y_pos:Number;
var attachedToPlayer:Boolean;
function Box(_x:Number, _y:Number) {
this.x_pos = _x;
this.y_pos = _y;
}
//other code here
}
See this tutorial on how to attach a class to an object in the library:
http://www.articlesbase.com/videos/5min/86620312
To create a new Box, you'd then use something like
box1 = new Box(100,200);
// creates a box at position 100x,200y
However, you'll also want to store the blocks you want to pickup into some sort of array so you can loop through them. See http://www.tech-recipes.com/rx/1383/flash-actionscript-create-an-array-of-objects-from-a-unique-class/
Example:
//somewhere near the top of your main method, or whereever your main game loop is running from - note Box.as would need to be in the same folder
import Box;
//...then, somewhere before your game loop
//create an array to hold the objects
var boxArray:Array = new Array();
//create loop with i as the counter
for (var i=0; i<4; i++)
{
var _x:Number = 100 + i;
var _y:Number = 100 + i;
//create Box object
var box:Box = new Box();
//assign text to the first variable.
//push the object into the array
boxArray.push(box);
}
Similarly, you would need a class for your player, and to create a new Player object at the start of your game, e.g.
var player = new Player(0,0);
You could then run a hittest method for your player against the blocks in your array for the main game loop (i.e. the loop that updates your player's position and other game properties). There are probably more efficient ways of doing this, e.g. only looping for the blocks that are currently on the screen.
Once your array has been created, use a foreach loop to run a hittest against your player in your game's main loop, e.g.
//assuming you have an array called 'boxArray' and player object called 'player'
for(var box in boxArray){
if (player.hittest(box)) {
player.attachObjectMethod(box);
}
}
This is basically pseudo-code for "for every box that we have entered into the array, check if the player is touching the box. If the box is touching, use the box as the argument for a method in the player class (which I have arbitrarily called attachObjectMethod)".
In attachObjectMethod, you could then define some sort of behavior for attaching the box to the player. For example, you could create a get and set method(s) for the x and y position of your boxes inside the box class, along with a boolean called something useful like attachedToPlayer. When attachObjectMethod was called, it would set the box's boolean, e.g. in the Player class
//include Box.as at the top of the file
import Box;
//other methods, e.g. constructor
//somewhere is the Player.as class/file
public function attachObjectMethod (box:Box) {
box.setattachedToPlayer(true);
//you could also update fields on the player, but for now this is all we need
}
Now the attachedToPlayer boolean of the box the player has collided with would be true. Back in our game loop, we would then modify our loop to update the position of the boxes:
//assuming you have an array called 'boxArray' and player object called 'player'
for(var box in boxArray){
if (player.hittest(box)) {
player.attachObjectMethod(box);
}
box.updatePosition(player.get_Xpos, player.get_Ypos);
}
In our Box class, we now need to define 'updatePosition':
//Box.as pseudo-code
class Box {
var x_pos:Number;
var y_pos:Number;
var attachedToPlayer:Boolean;
function Box(box_x:Number, box_y:Number) {
this.x_pos = box_x;
this.y_pos = box_y;
}
public function updatePosition(_x:Number, _y:Number) {
if (this.attachedToPlayer) {
this.x_pos = _x;
this.y_pos = _y;
}
}
//other code here
}
As you can see we can pass the player's position, and update the box's position if the attachedToPlayer boolean has been set. Finally, we add a move method to the box:
public function move() {
if (this.attachedToPlayer) {
this._x = x_pos;
this._y = y_pos;
}
}
Examples of updating position:
http://www.swinburne.edu.au/design/tutorials/P-flash/T-How-to-smoothly-slide-objects-around-in-Flash/ID-17/
Finally, to make it all work we need to call the move method in the game loop:
//assuming you have an array called 'boxArray' and player object called 'player'
for(var box in boxArray){
if (player.hittest(box)) {
player.attachObjectMethod(box);
}
box.updatePosition(player.get_Xpos, player.get_Ypos);
box.move();
}
You have also specified that the blocks should only move with the player if they have nothing on top of them. When you call your attachedToPlayer method, you would also need to run a foreach loop inside the method between the box and the objects that might sit on top of the box. You should now have a fair idea from the above code how to do this.
I appreciate that this is quite a lengthy answer, and I haven't had an opportunity to test all the code (in fact I'm fairly positive I made a mistake somewhere) - don't hesitate to ask questions. My other advice is to understand the concepts thoroughly, and then write your own code one bit at a time.
Good luck!
The way I would do this is to design an individual hit test for each block he will be picking up, then code for the hit test to play a frame within the sprite's timeline of him carrying a block, and to play a frame within the block to be picked up's timeline of the block no longer at rest (disappeared?).
Good Luck if you're confused about what I've said just ask a little more about it and I'll try to help you if I can.
After the user goes through the Setup Wizard, and makes a few choices, the usual thing is to display the VerifyReadyDlg to say "Are you ready to install?"
The built-in VerifyReadyDlg is static. It does not present a summary of the choices he made previously. I'd like to modify it so that it does.
How can I do that?
Example
"Static" text:
Intelligent text:
I don't believe I can modify the Control table in the MSI, because mods during the installation process are not allowed. I found MsiViewModifyInsertTemporary, but I don't think that will work either. The relevant row in the Control table is already present, and it contains static data. I want to modify the data, just before VerifyReadyDlg is displayed.
You may not be able to modify existing rows in the MSI tables, but you can insert new "temporary" rows.
So, in a custom action, at runtime, insert one or more temporary rows into the Control table. In Javascript, it looks like this:
var controlView = Session.Database.OpenView("SELECT * FROM Control");
controlView.Execute();
var record = Session.Installer.CreateRecord(12);
record.StringData(1) = "VerifyReadyDlg"; // Dialog_ - the dialog to mod
record.StringData(2) = "CustomVerifyText1"; // Control - any unique name will do
record.StringData(3) = "Text"; // Type
record.IntegerData(4) = 25; // X
record.IntegerData(5) = 70; // Y
record.IntegerData(6) = 320; // Width
record.IntegerData(7) = 65; // Height
record.IntegerData(8) = 2; // Attributes
record.StringData(9) = ""; // Property
record.StringData(10) = text1; // Text - the text to be displayed
record.StringData(11) = ""; // Control_Next
record.StringData(12) = ""; // Help
controlView.Modify(MsiViewModify.InsertTemporary, record);
controlView.Close();
You probably want that custom text to be displayed only upon INSTALL. In that case, add a condition, in the same way:
var controlCondView = Session.Database.OpenView("SELECT * FROM ControlCondition");
controlCondView.Execute();
record = Session.Installer.CreateRecord(4);
record.StringData(1) = "VerifyReadyDlg"; // Dialog_
record.StringData(2) = "CustomVerifyText1"; // Control_ - same name as above
record.StringData(3) = "Show"; // Action
record.StringData(4) = "NOT Installed"; // Condition
controlCondView.Modify(MsiViewModify.InsertTemporary, record);
controlCondView.Close();
The Msi constants are defined like this:
// http://msdn.microsoft.com/en-us/library/aa372516(VS.85).aspx
var MsiViewModify =
{
Refresh : 0,
Insert : 1,
Update : 2,
Assign : 3,
Replace : 4,
Merge : 5,
Delete : 6,
InsertTemporary : 7, // cannot permanently modify the MSI during install
Validate : 8,
ValidateNew : 9,
ValidateField : 10,
ValidateDelete : 11
};
A couple notes:
The InstallText in the Control table is normally displayed. It can be customized with a .wxl file, inserting something like this:
<String Id="VerifyReadyDlgInstallText">Whatever.</String>
This results in a row in the Control table. But you cannot remove rows from the table at runtime.
If you choose the X,Y and Height,Width for your new custom text to be the same as for the static InstallText, the InstallText will be obscured.
It may seem counter-intuitive to use "NOT Installed" as the condition - but remember, this is the state of the world prior to running the Setup Wizard. If the MSI is Installed prior to running the Wizard, then you're probably not installing it, which means you don't need to display the choices being made in the wizard.
Of course you can add multiple controls this way. You could add multiple Text controls, or...You can add lines, buttons, checkboxes, whatever. For each one, you'll have to set the control type and geometry appropriately. Use Orca to examine the Control table to figure out how.
This approach works for any Dialog. You only have to be sure to run the custom action to insert the temp rows into the Control table, at some point in the InstallUISequence, before the Dialog is rendered.