PowerBuilder, disable system menu`s close button

ulong ll_parent_hwnd
ulong ll_sys_menu_hwnd
ulong ll_sys_menu_close_flags
ulong ll_ret

n_cst_numerical u_num

ll_parent_hwnd = Handle(this.parentwindow())

ll_sys_menu_hwnd = GetSystemMenu(ll_parent_hwnd, FALSE)

ll_sys_menu_close_flags = GetMenuState(ll_sys_menu_hwnd, SC_CLOSE, MF_BYCOMMAND )

ll_ret = u_num.of_bitwiseand(ll_sys_menu_close_flags , MF_DISABLED)

ib_close_prev_enabled = (ll_ret = 0)

If ib_close_prev_enabled Then
EnableMenuItem (ll_sys_menu_hwnd, SC_CLOSE, MF_BYCOMMAND + MF_DISABLED + MF_GRAYED)
End If

 

And to enable it later:

If ib_close_prev_enabled Then
EnableMenuItem (GetSystemMenu(handle(parentwindow()), FALSE), SC_CLOSE, MF_BYCOMMAND + MF_ENABLED)
End If

 

PowerBuilder, different DD list values for each row, another way

The Ol’ Hidden Items in the Dddw Problem Part II

Make a second copy of the Color column and have this always contain all the rows in its dddw.  This second column is never filtered.

When the row is not the current row, display the column with the unfiltered dddw and hide the filter column.  If the row is the current row, show the column with the filtered dddw, and hide the column with the dddw with all the possible rows.  To do this, add the following expression to the visibility attribute of the column with the dddw which gets filtered:

IF (CurrentRow() = GetRow(), 1, 0)

The column with the dddw which always contains all the values will have the following expression in its visibility attribute:

IF (CurrentRow() = GetRow(), 0, 1)

PowerBuilder, different DD list values for each row

Source http://www.pbdr.com/pbtips/dw/fltrdddw.htm

Step 1 – declare instance variables

boolean ib_dropdowndropped = False
boolean ib_dropdownredrawn = True

Step 2 – extend the pbm_dropdown event

ib_dropdowndropped = True
ib_dropdownredrawn = False
of_Filter(True)
ib_dropdownredrawn = True

Step 3 – extend the pbm_ncpaint event

If (ib_dropdowndropped And ib_dropdownredrawn) Then
 ib_dropdowndropped = False
 ib_dropdownredrawn = False
 of_Filter(False)
 ib_dropdownredrawn = True
End If

Step 4 – write the of_Filter (boolean ab_switch) subroutine

datawindowchild ldwc
long ll_getitemnumber
string ls_setfilter = ""

If (ab_switch) Then
 ll_getitemnumber = GetItemNumber(GetRow(), "order_status_id")
 If (ll_getitemnumber = 1) Then // cancelled -> cancelled
  ls_setfilter = "(order_status_id = 1)"
 ElseIf (ll_getitemnumber = 2) Then // confirmed -> confirmed
  ls_setfilter = "(order_status_id = 2)"
 ElseIf (ll_getitemnumber = 3) Then // new -> cancelled, new, pending
  ls_setfilter = "(order_status_id = 1) or (order_status_id = 3) or
(order_status_id = 4)"
 ElseIf (ll_getitemnumber = 4) Then // pending -> cancelled, confirmed,
pending
  ls_setfilter = "(order_status_id = 1) or (order_status_id = 2) or
(order_status_id = 4)"
 End If
End If

GetChild("order_status_id", ldwc)
ldwc.SetFilter(ls_setfilter)
ldwc.Filter()

Bowerbuilder datawindow autosize problem

You have a datawindow. Datawindow has an Autosize Height set to Details band. You insert a row, set a long string value to some field expecting that field to be auto-sized. And it is, but you don’t see a text as Details band does not auto-size. What to do? Whan way to fix this is to call Sort() somewhere after you set v the value fro the datawindow to refresh and auto-size to take effect. But that does not work all times ( for example … you dont want to sort data now). Another way is to set:

dw.Modify ( ‘DataWindow.Header.Height.AutoSize=yes’)

This will also make datawindow to resize all the bands and auto-size will take effect then.

BattleCity game using Phaser.IO, part 4 – simple collision.

In the last part we created moving player tank in our city, but it can move anywhere through the walls without any collision. So in this part we will investigate hwo to enable collision detection between our player tank and city walls. Also we will enable and outputt some debugging information to better understand what exactly happens on our map.

To enable collision between our tank and walls/city  we have to enable collision for tiles ( now we will just enable collision for all tiles of our tile set ). In  create function, after add tileset, add:

map.setCollisionBetween(1, 10000);
Also we have to enable player tank physics, in create function, after game add sprite, we add:
game.physics.enable(player_tank);
player_tank.body.collideWorldBounds = true;
In update function we add collision check of player vs layer:
game.physics.arcade.collide(player_tank, layer);
One note: after doing all this, collision still was not working. I found that it was realated to scaling. You should change layer.scale.set(2); to layer.setScale(); and it is fixed.

Debugging collision. To see collision rectangles you could add

layer.debug = true;

after layer creation and also add a render callback function (in new Phaser.Game you should add

function render() {

    //  Useful debug things you can turn on to see what's happening

    // game.debug.spriteBounds(sprite);
    // game.debug.cameraInfo(game.camera, 32, 32);
    // game.debug.body(sprite);
    game.debug.bodyInfo(player_tank, 10, 10);

    game.debug.body(player_tank);

}
Also, after enabling debugging, you can see that tank image is smaller than sprite itself but collision happens on sprite size. To deal with it we could change player tank body size on each key press like that:
    if (cursors.left.isDown)
    {
        //if left cursor is down - play left animation, add velocity
        player_tank.animations.play('left');
        player_tank.body.velocity.x = -100;
        player_tank.body.setSize(13,13,2,1);
        
    }
So after all, your index.html should look something like this:
<!doctype html> 
<html lang="en"> 
<head> 
	<meta charset="UTF-8" />
	<title>Battlecity</title>
	<script type="text/javascript" src="js/phaser.js"></script>
    <style type="text/css">
        body {
            margin: 0;
        }
    </style>
</head>
<body>

<script type="text/javascript">

var game = new Phaser.Game(512, 480, Phaser.AUTO, '', { preload: preload, create: create, update: update, render: render });


function preload() {
    game.load.tilemap('tilemap', 'assets/tilemaps/maps/battlecity_map1.json', null, Phaser.Tilemap.TILED_JSON);
    game.load.image('tiles16x16', 'assets/tilemaps/tiles/battlecity_general.png');
    // load spritesheet for our player and enemies, all of them use same spritesheet
    game.load.spritesheet('tanks', 'assets/tilemaps/tiles/battlecity_general.png', 16, 16);
}

var map;
var layer;
var player_tank;
var cursors; 

function create() {
    game.stage.backgroundColor = '#787878';

    map = game.add.tilemap('tilemap');
    map.addTilesetImage('battlecity','tiles16x16');
    map.setCollisionBetween(1, 10000);
    

    layer = map.createLayer('Ground');
    layer.setScale(2);
    layer.debug = true;
    layer.resizeWorld();

    //create cursor key handler
    cursors = game.input.keyboard.createCursorKeys();
   
    //create our player tank, position it at x,y and use sprite sheet 'tanks'
    player_tank = this.game.add.sprite(135, 448, 'tanks');
    game.physics.enable(player_tank);
    player_tank.body.collideWorldBounds = true; 
    player_tank.frame = 0;
    player_tank.scale.set(2);
    player_tank.animations.add('left', [2,3], 10, true);
    player_tank.animations.add('right', [6,7], 10, true);
    player_tank.animations.add('up', [0,1], 10, true);
    player_tank.animations.add('down', [4,5], 10, true);
    
}

function update() {
    game.physics.arcade.collide(player_tank, layer);
    
    if (cursors.left.isDown)
    {
        //if left cursor is down - play left animation, add velocity
        player_tank.animations.play('left');
        player_tank.body.velocity.x = -100;
        player_tank.body.setSize(13,13,2,1);
        
    }
    else if (cursors.right.isDown)
    {
        player_tank.animations.play('right');
        player_tank.body.velocity.x = 100;
        player_tank.body.setSize(13,13,1,1);
    }
    else if (cursors.up.isDown)
    {
        player_tank.animations.play('up');
        player_tank.body.velocity.y = -100;
        player_tank.body.setSize(13,13,1,2);
    }
    else if (cursors.down.isDown)
    {
        player_tank.animations.play('down');
        player_tank.body.velocity.y = 100;
        player_tank.body.setSize(13,13,1,1);
    } 
    else 
    {
        player_tank.animations.stop();
        player_tank.body.velocity.set(0);
    }
}

function render() {

    //  Useful debug things you can turn on to see what's happening

    // game.debug.spriteBounds(sprite);
    // game.debug.cameraInfo(game.camera, 32, 32);
    // game.debug.body(sprite);
    game.debug.bodyInfo(player_tank, 10, 10);

    game.debug.body(player_tank);

}

</script>

</body>
</html>

So, with enabled collision and moving player tank, that is what we have at this moment:

BattleCity game using Phaser.IO, part 3 – using Visual Studio Code.

This will be a little go back to setting up development environment. I have noticed that in some networks c9users.io is blocked by network providers firewall, that complicates developing using Cloud9 – you will net be able to preview your project.

Another good tool you could use is Visual Studio Code.

Download the tool, install it. As we already have our project in github, just select Clone Git repository, enter your repository url and credentials and that is it.

To have a quick way of previewing of our project without moving to server you can go to Extensions, search for Live Server Extension.

Visual Studio Code - live server install
Visual Studio Code – live server install

By pressing Go Live you will be able to quickly host your files and preview locally.

Visual Studio Code - go live
Visual Studio Code – go live

Visual Studio Code has nice source control integration so you will be able to view your changes and commit and push them from UI.

Visual Studio Code - source control
Visual Studio Code – source control

 

Creating a BattleCity game using Phaser.IO, part 1

I was never a huge fan of JavaScript and I am no way front-end developer, but I like some ideas from that technology and now with dying Flash – it is definitely the future.

So in this post series, I will be making famous Nintendo (NES) Battlecity game clone using Phaser.IO, just for fun, to see how it works. To make it I decided to use some online development environment, Github for source control and .. yes that is basically all that one will need.

Setting up a development environment.

For a development environment, i have decided to code everything online using Cloud9 and Github.

First login or create your Github account. Then create a new repository.

Then you have to register for the Coud9 account and create workspace there. When creating workspace select Html5 and provide your Github repository URL in “Clone from Git..” field.

Also, go to Cloud9 settings, select SSH Keys, copy your key and then go to Github->Settings->SSH and…, press New SSH key, name it something like C9 and then paste your key and press Add SSH key.

Setting up project workspace.

In Cloud9 workspace of your project create folders:

  • assets->tilemaps->maps
  • assets->tilemaps->tiles
  • js

Create empty index.html in your main folder.

Go to phaser.io and download phaser.js then move it to js folder.

Creating tiles map.

Go to sprites resource and download Battlecity sprites (or download them here):

Download Tiled map editor, its the tool we will use to make our maps.

Start Tiled and select File->New tilest. As source select your downloaded sprites file ( i have named it /battlecity_general.png ). Set 16px for tile width and tile height.

Then select File->New map. Width 16 tiles, Height 15 tiles. Tile size 16 px.

Using your tileset draw your map ( I have used Battlecity level 1 as reference ).

Important: press embed tileset button in your map editor. That way your tilesets will be embedded to your exported JSON file.

Next, after you finish creating your map, select File->Export as and select JSON format.

Then you have to move your resources to your project workspace in Cloud9.

  • Move JSON file to maps folder.
  • Move general tiles png file to tiles folder.

Your files now should look something like that:

Loading tile map.

Now let’s populate your index.html with some HTML and JavaScript code:



<!doctype html> 
<html lang="en"> 
<head> 
	<meta charset="UTF-8" />
	<title>Battlecity</title>
	<script type="text/javascript" src="js/phaser.js"></script>
    <style type="text/css">
        body {
            margin: 0;
        }
    </style>
</head>
<body>

<script type="text/javascript">

var game = new Phaser.Game(512, 480, Phaser.AUTO, '', { preload: preload, create: create, update: update });


function preload() {
    game.load.tilemap('tilemap', 'assets/tilemaps/maps/battlecity_map1.json', null, Phaser.Tilemap.TILED_JSON);
    game.load.image('tiles16x16', 'assets/tilemaps/tiles/battlecity_general.png');
}

var map;
var layer;


function create() {
    game.stage.backgroundColor = '#787878';

    map = game.add.tilemap('tilemap');
    map.addTilesetImage('battlecity','tiles16x16');
    
    layer = map.createLayer('Ground');
    layer.scale.set(2);
}

function update() {
}

</script>

</body>
</html>

My json file:

{ "height":15,
"layers":[
{
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 18, 17, 0, 17, 20, 0, 0, 17, 0, 17, 0, 0, 17, 0, 17, 0, 18, 17, 0, 17, 20, 0, 0, 17, 0, 17, 0, 0, 17, 0, 17, 0, 18, 17, 0, 17, 20, 0, 0, 17, 0, 17, 0, 0, 17, 0, 17, 0, 18, 17, 42, 17, 20, 0, 0, 17, 0, 17, 0, 0, 17, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 0, 0, 0, 0, 0, 18, 20, 0, 18, 20, 0, 0, 0, 0, 0, 0, 19, 0, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 0, 19, 46, 0, 0, 0, 0, 18, 17, 19, 17, 20, 0, 0, 0, 0, 0, 46, 0, 0, 0, 0, 0, 18, 17, 17, 17, 20, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 18, 17, 0, 17, 20, 0, 0, 17, 0, 17, 0, 0, 17, 0, 17, 0, 18, 17, 0, 17, 20, 0, 0, 17, 0, 17, 0, 0, 17, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 17, 0, 0, 17, 0, 17, 0, 0, 18, 17, 20, 0, 0, 0, 17, 0, 17, 0, 0, 0, 0, 0, 26, 0, 18, 70, 20, 0, 0, 0, 0, 0, 0, 0],
"height":15,
"name":"Ground",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":16,
"x":0,
"y":0
}],
"nextobjectid":1,
"orientation":"orthogonal",
"renderorder":"right-down",
"tiledversion":"1.0.3",
"tileheight":16,
"tilesets":[
{
"columns":25,
"firstgid":1,
"image":"battlecity_general.png",
"imageheight":256,
"imagewidth":400,
"margin":0,
"name":"battlecity",
"spacing":0,
"tilecount":400,
"tileheight":16,
"tilewidth":16
}],
"tilewidth":16,
"type":"map",
"version":1,
"width":16
}

If you did everything correctly, then after pressing Run and preview you should get something like that:

If it does not work check paths in load.tilemap and load.image functions.

Also in map.addTilesetImage(‘battlecity’,’tiles16x16′);

tiles16x16 is image name used in load.image.

battlecity is tileset name in json file, check it also.

At the end, let’s push everything to our GIT repository. In bash tab execute these commands:

  • git init
  • git add .
  • git commit -m “first commit”
  • git push

After git push you probably will be prompted to enter your GitHub username and password, so do that.

That all for this time, next time we will make something to move.

Calling .NET from PowerBuilder

To call .NET for PowerBuilder best option is to create Class Library in Visual Studio. Sign it. In project properties, Application, Assembly Information…, check “Make assembly COM-Visible”.

Sign it class library (project properties, Signing…).

In project properties, Application, Assembly Information…, check “Make assembly COM-Visible”.

Optional, add these attributes to your class:
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId(“ClassLibrary1.Class1”)]

Register created DLL in command lime like:

regasm /tlb “path/to/dll/file.dll” /codebase

Use it from PowerBuilder like:


OLEObject obj

Integer li_rc

obj = CREATE OLEObject
li_rc = obj.ConnectToNewObject("ClassLibrary1.Class1")

IF li_rc &lt; 0 THEN

DESTROY obj MessageBox("Connecting to COM Object Failed",     "Error: " + String(li_rc)) Return

MessageBox("Connecting to COM Object Failed",     "Error: " + String(li_rc)) Return

Return

ELSE obj.ShowMe()END IF

obj.ShowMe()

END IF

To call some web service from this DLL you add service reference and then:

BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress address =
new EndpointAddress("http://web-service-url");
var client = new ServiceReference1.YourWebServiceClient(binding, address);

var b = client.YourWebServiceMethod();

List services problem in Windows 10 and PowerBuilder .NET 12.5

Windows 10 / PowerBuilder .NET 12.5

Trying to make web service client and list services I get an error:

Windows SDK for .Net Framework 4.0 was not installed. Please install it before use this feature.

Tried to install Microsoft Windows SDK for Windows 7 and .NET Framework 4 (ISO) but that did not help.

So I downloaded ProcessMonitor to check what for PowerBuilder .NET is looking and cannot find.  Found that it is looking for [HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools-x86] and does not find it.

In my registry, I had tools in v8.0A WinSDK-NetFx35Tools-X86, so I just for test I made this new registry entry:

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SDKs\Windows\v7.1\WinSDK-NetFx40Tools-x86]
“ProductVersion”=”8.0.50727”
“ComponentName”=”Microsoft Visual Studio 2012 Multi-targeting Utilities for .NET Framework 3.5”
“InstallationFolder”=”C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v7.0A\\bin\\”

And after that, list services now work in PowerBuilder .NET 12.5