AutoIT script - Compare Paint's Rotated Image with GDI's rotated image - image

I have an image and rotate it with both MS Paint and GDI. I want to show that the rotated image from both methods are the same.
Here is the code I have to rotate image with GDI
#include <GDIPlus.au3>
_GDIPlus_Startup()
$hImage1 = _GDIPlus_ImageLoadFromFile(#ScriptDir & "\Picture.gif")
$hGraphic1 = _GDIPlus_ImageGetGraphicsContext($hImage1)
$hImage2 = _GDIPlus_BitmapCreateFromGraphics(_GDIPlus_ImageGetWidth($hImage1), _GDIPlus_ImageGetHeight($hImage1), $hGraphic1)
$hGraphic2 = _GDIPlus_ImageGetGraphicsContext($hImage2)
$matrix = _GDIPlus_MatrixCreate()
_GDIPlus_MatrixRotate($matrix,90)
_GDIPlus_GraphicsSetTransform($hGraphic2, $matrix)
_GDIPlus_GraphicsDrawImage($hGraphic2, $hImage1, 0, -590)
_GDIPlus_ImageSaveToFile($hImage2, #ScriptDir & "\out.gif")
_GDIPlus_MatrixDispose($matrix)
_GDIPlus_GraphicsDispose($hGraphic1)
_GDIPlus_GraphicsDispose($hGraphic2)
_GDIPlus_ImageDispose($hImage1)
_GDIPlus_ImageDispose($hImage2)
_GDIPlus_ShutDown ()
Then I used this code to compare 2 images:
$bm1 = _GDIPlus_ImageLoadFromFile(#ScriptDir & "\Picture1.gif")
$bm2 = _GDIPlus_ImageLoadFromFile(#ScriptDir & "\out.gif")
if ComparePicture($bm1, $bm2) == True Then
MsgBox(0, "Test result", "Same image!")
Else
MsgBox(0, "Test result", "Different image!")
EndIf
_GDIPlus_ImageDispose($bm1)
_GDIPlus_ImageDispose($bm2)
_GDIPlus_Shutdown()
Func ComparePicture($bm1, $bm2)
$Bm1W = _GDIPlus_ImageGetWidth($bm1)
$Bm1H = _GDIPlus_ImageGetHeight($bm1)
$BitmapData1 = _GDIPlus_BitmapLockBits($bm1, 0, 0, $Bm1W, $Bm1H, $GDIP_ILMREAD, $GDIP_PXF08INDEXED )
$Stride = DllStructGetData($BitmapData1, "Stride")
$Scan0 = DllStructGetData($BitmapData1, "Scan0")
$ptr1 = $Scan0
$size1 = ($Bm1H - 1) * $Stride + ($Bm1W - 1) * 4
$Bm2W = _GDIPlus_ImageGetWidth($bm2)
$Bm2H = _GDIPlus_ImageGetHeight($bm2)
$BitmapData2 = _GDIPlus_BitmapLockBits($bm2, 0, 0, $Bm2W, $Bm2H, $GDIP_ILMREAD, $GDIP_PXF08INDEXED)
$Stride = DllStructGetData($BitmapData2, "Stride")
$Scan0 = DllStructGetData($BitmapData2, "Scan0")
$ptr2 = $Scan0
$size2 = ($Bm2H - 1) * $Stride + ($Bm2W - 1) * 4
$smallest = $size1
If $size2 < $smallest Then $smallest = $size2
$call = DllCall("msvcrt.dll", "int:cdecl", "memcmp", "ptr", $ptr1, "ptr", $ptr2, "int", $smallest)
_GDIPlus_BitmapUnlockBits($bm1, $BitmapData1)
_GDIPlus_BitmapUnlockBits($bm2, $BitmapData2)
Return ($call[0]=0)
EndFunc
I tried changing the file type, color depth, etc. but I could not get the code to show that they are the same. When I do not rotate the picture i.e
_GDIPlus_MatrixRotate($matrix,0)
then it recognize the same image. When I rotate right 90, it doesn't. Does anyone knows what might be going on?
Thanks
For reference, this question has also been asked on the AutoIt forums here.

I think $GDIP_PXF08INDEXED is modifying the images differently. Try it without setting it and it should work.
Furthermore, you can use this code to flip the image:
$hImage1 = _GDIPlus_ImageLoadFromFile(#ScriptDir & "\Picture1.gif")
_GDIPlus_ImageRotateFlip($hImage1, 1) ;90°
_GDIPlus_ImageSaveToFile($hImage1, #ScriptDir & "\out.gif")
_GDIPlus_ImageDispose($hImage1)
Br,
UEZ

Related

Create Box or vertical line offsetting session time which splits using Fibonacci ratio

I have completed the main objective of dividing the day into "cycles". Now, I am having trouble with creating a "sub cycle" within each zone that is defined. I basically am trying to take a cycle (sesionTime1) and split that at 0.38 and 0.62 be it with a vertical line that only goes from the overall session high/low, or just create another box where the start of the box is at the 0.38 and the end of the box is at 0.62. I have tried defining sessionTime1 * 0.38, but thats not working for me. And, using bar_indez(X) only focuses on the bar movement which will change as the timeframe on chart is changed.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © hitmanict
//#version=5
indicator("AMD", overlay=true)
//Get boolean input value (on/off buttons)
//Accumulation
inputAcc = input.bool(title = "Accumulation", defval = true, tooltip = "Turn On/Off Accumulation & Select Color", inline = "1", group = "Accumulation")
inputAccColor = input.color(title = "Box", defval = color.new(#4caf50, 90), inline = "2", group = "Accumulation")
InputAccBorder = input.color(title = "Border", defval = color.rgb(0, 0, 0, 95), inline = "2", group = "Accumulation")
inputAccSub = input.bool(title = "Accumulation Fractal", defval = true, group = "Accumulation")
sessionTime1 = input.session("1845-0330", title = "Session Time")
sessionZone1 = input.string("GMT-5", title = "Session Time Zone")
//Manipulation
inputMan = input.bool(title = "Manipulation", defval = true, tooltip = "Turn On/Off Manipulation & Select Color", inline = "3", group = "Manipulation")
inputManColor = input.color(title = "Box", defval = color.new(#ffcc80,80), inline = "4", group = "Manipulation")
InputManBorder = input.color(title = "Border", defval = color.rgb(0, 0, 0, 95), inline = "4", group = "Manipulation")
sessionTime2 = input.session("0330-0900", title = "Session Time")
sessionZone2 = input.string("GMT-5", title = "Session Time Zone")
//Distribution
inputDistro = input.bool(title = "Distribution", defval = true, tooltip = "Turn On/Off Distribution & Select Color", inline = "5", group = "Distribution")
inputDistColor = input.color(title = "Box", defval = color.new(#2962ff,95), inline = "6", group = "Distribution")
InputDistBorder = input.color(title = "Border", defval = color.rgb(0, 0, 0, 95), inline = "6", group = "Distribution")
sessionTime3 = input.session("0900-1845", title = "Session Time")
sessionZone3 = input.string("GMT-5", title = "Session Time Zone")
//InSession() returns 'true' when the current bar happens inside
//the specified session, corrected for the given time zone (optional).
//Returns 'false' when the bar doesn't happen in that time period,
//or when the chart's time frame is 1 day or higher.
InSession1(sessionTime1, sessionZone1=syminfo.timezone) => not na(time(timeframe.period, sessionTime1, sessionZone1))
InSession2(sessionTime2, sessionZone1=syminfo.timezone) => not na(time(timeframe.period, sessionTime2, sessionZone2))
InSession3(sessionTime3, sessionZone1=syminfo.timezone) => not na(time(timeframe.period, sessionTime3, sessionZone3))
//See if the session is currently active and just started
inSession1 = InSession1(sessionTime1, sessionZone1) and timeframe.isintraday
session1Start = inSession1 and not inSession1[1]
inSession2 = InSession2(sessionTime2, sessionZone2) and timeframe.isintraday
session2Start = inSession2 and not inSession2[1]
inSession3 = InSession3(sessionTime3, sessionZone3) and timeframe.isintraday
session3Start = inSession3 and not inSession3[1]
//Create variables
var session1HighPrice = 0.0
var session1LowPrice = 0.0
var session2HighPrice = 0.0
var session2LowPrice = 0.0
var session3HighPrice = 0.0
var session3LowPrice = 0.0
//When a new session starts, set high/low to the data of the bar in the session.
if session1Start
session1HighPrice := high
session1LowPrice := low
if session2Start
session2HighPrice := high
session2LowPrice := low
if session3Start
session3HighPrice := high
session3LowPrice := low
//Else, during the session, track the highest high and lowest low
else if inSession1
session1HighPrice := math.max(session1HighPrice, high)
session1LowPrice := math.min(session1LowPrice, low)
else if inSession2
session2HighPrice := math.max(session2HighPrice, high)
session2LowPrice := math.min(session2LowPrice, low)
else if inSession3
session3HighPrice := math.max(session3HighPrice, high)
session3LowPrice := math.min(session3LowPrice, low)
//Create persistent variable for the box identifier
var box session1Box = na
var box session2Box = na
var box session3Box = na
//When a session begins, make a new box for that session
if session1Start
session1Box := inputAcc ? box.new(left=bar_index, top = na, right = na, bottom = na, bgcolor = inputAccColor, border_color = InputAccBorder) : na
if session2Start
session2Box := inputMan ? box.new(left=bar_index, top = na, right = na, bottom = na, bgcolor = inputManColor, border_color = InputManBorder) : na
if session3Start
session3Box := inputDistro ? box.new(left=bar_index, top = na, right = na, bottom = na, bgcolor = inputDistColor, border_color = InputDistBorder) : na
//During the session, update that session's existing box
if inSession1
box.set_top(session1Box, session1HighPrice)
box.set_bottom(session1Box, session1LowPrice)
box.set_right(session1Box, bar_index + 1)
if inSession2
box.set_top(session2Box, session2HighPrice)
box.set_bottom(session2Box, session2LowPrice)
box.set_right(session2Box, bar_index + 1)
if inSession3
box.set_top(session3Box, session3HighPrice)
box.set_bottom(session3Box, session3LowPrice)
box.set_right(session3Box, bar_index + 1)
*//Sub AMD Section*
//Create persistent variable for the sub box identifier
var box session1BoxSub = na
var box session2BoxSub = na
var box session3BoxSub = na
if session1Start
session1BoxSub := inputAcc == inputAccSub ? box.new(left = bar_index, top = na, right = na, bottom = na, bgcolor = color.rgb(0, 187, 212, 100), border_color = color.rgb(171, 173, 177), border_style = line.style_dotted, border_width = 2) : na
if inSession1
box.set_top(session1BoxSub, session1HighPrice)
box.set_bottom(session1BoxSub, session1LowPrice)
box.set_right(session1BoxSub, bar_index + 1)
I am attempting this addition at the very bottom unde3r SUB AMD SECTION. Any help/guidance is greatly appreciated.

PrintPreviewControl & Form Design working differently on another OS. VB.NET

im writing an app for accountings of small hotel, i'm working with Visual Studio 2013, on OS: windows 10 (Laptop). After finishing the app just published it using publish wizard, then everything was going great till i copied the published files to another computer contains OS: Windows 7 SP1, the app worked successfully but with a little changes in form design and while preview reports printing.
Here's two pictures to explain what is exactly the problem...
If anyone could explain what's going on and what to do to solve this issue would be respected.
Here's my class which contains printpreviewcontrol code:
Private mRow As Integer = 0
Private newpage As Boolean = True
Private Sub PrintDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
Try
Dim font36 = New Font("Playball", 36, FontStyle.Regular)
Dim font8 = New Font("Lora", 8, FontStyle.Regular)
Dim font20 = New Font("Lora", 20, FontStyle.Underline)
Dim font16 = New Font("Lora", 16, FontStyle.Regular)
e.Graphics.DrawString("Riviera Beach Chalets", font36, Brushes.Black, New Rectangle(150, 25, 800, 100))
e.Graphics.DrawString("Accounting Reports", font20, Brushes.Black, New Rectangle(650, 45, 300, 50))
e.Graphics.FillRectangle(Brushes.MistyRose, New Rectangle(101, 741, 19, 19))
e.Graphics.DrawString("Accommondation Revenue or Beach Revenue or CoffeeShop Revenue is 0", font8, Brushes.Black, New Rectangle(125, 745, 500, 30))
e.Graphics.DrawString("Amount Received Total :", font16, Brushes.Black, New Rectangle(570, 735, 500, 50))
e.Graphics.DrawString(Report_Database.reporttot, font16, Brushes.Black, New Rectangle(850, 735, 500, 50))
' sets it to show '...' for long text
Dim fmt As StringFormat = New StringFormat(StringFormatFlags.LineLimit)
fmt.LineAlignment = StringAlignment.Center
fmt.Trimming = StringTrimming.EllipsisCharacter
Dim y As Int32 = e.MarginBounds.Top
Dim rc As Rectangle
Dim x As Int32
Dim h As Int32 = 0
Dim row As DataGridViewRow
' print the header text for a new page
' use a grey bg just like the control
If newpage Then
row = Report_Database.DataGridView1.Rows(mRow)
x = 50
For Each cell As DataGridViewCell In row.Cells
' since we are printing the control's view,
' skip invidible columns
If cell.Visible Then
rc = New Rectangle(x, y, cell.Size.Width, cell.Size.Height)
e.Graphics.FillRectangle(Brushes.LightGray, rc)
e.Graphics.DrawRectangle(Pens.Black, rc)
' reused in the data pront - should be a function
Select Case Report_Database.DataGridView1.Columns(cell.ColumnIndex).DefaultCellStyle.Alignment
Case DataGridViewContentAlignment.BottomRight,
DataGridViewContentAlignment.MiddleRight
fmt.Alignment = StringAlignment.Far
rc.Offset(-1, 0)
Case DataGridViewContentAlignment.BottomCenter,
DataGridViewContentAlignment.MiddleCenter
fmt.Alignment = StringAlignment.Center
Case Else
fmt.Alignment = StringAlignment.Near
rc.Offset(2, 0)
End Select
e.Graphics.DrawString(Report_Database.DataGridView1.Columns(cell.ColumnIndex).HeaderText,
Report_Database.DataGridView1.Font, Brushes.Black, rc, fmt)
x += rc.Width
h = Math.Max(h, rc.Height)
End If
Next
y += h
End If
newpage = False
' now print the data for each row
Dim thisNDX As Int32
For thisNDX = mRow To Report_Database.DataGridView1.RowCount - 1
' no need to try to print the new row
If Report_Database.DataGridView1.Rows(thisNDX).IsNewRow Then Exit For
row = Report_Database.DataGridView1.Rows(thisNDX)
h = 0
' reset X for data
x = 50
' print the data
For Each cell As DataGridViewCell In row.Cells
If cell.Visible Then
rc = New Rectangle(x, y, cell.Size.Width, cell.Size.Height)
' SAMPLE CODE: How To
' up a RowPrePaint rule
If Val(row.Cells(2).Value) = 0 Or Val(row.Cells(3).Value) = 0 Or Val(row.Cells(4).Value) = 0 Then
Using br As New SolidBrush(Color.MistyRose)
e.Graphics.FillRectangle(br, rc)
End Using
End If
e.Graphics.DrawRectangle(Pens.Black, rc)
Select Case Report_Database.DataGridView1.Columns(cell.ColumnIndex).DefaultCellStyle.Alignment
Case DataGridViewContentAlignment.BottomRight,
DataGridViewContentAlignment.MiddleRight
fmt.Alignment = StringAlignment.Far
rc.Offset(-1, 0)
Case DataGridViewContentAlignment.BottomCenter,
DataGridViewContentAlignment.MiddleCenter
fmt.Alignment = StringAlignment.Center
Case Else
fmt.Alignment = StringAlignment.Near
rc.Offset(2, 0)
End Select
e.Graphics.DrawString(cell.FormattedValue.ToString(),
Report_Database.DataGridView1.Font, Brushes.Black, rc, fmt)
x += rc.Width
h = Math.Max(h, rc.Height)
End If
Next
y += h
' next row to print
mRow = thisNDX + 1
If y + h > e.MarginBounds.Bottom Then
e.HasMorePages = True
' mRow -= 1 causes last row to rePrint on next page
newpage = True
Button1.Enabled = True
Button4.Enabled = True
If mRow = Report_Database.DataGridView1.RowCount Then
e.HasMorePages = False
Exit Sub
End If
Return
End If
Next
Catch ex As Exception
MsgBox(ex.ToString, MsgBoxStyle.Critical)
End Try

Minor Syntax issue regarding Swift 3.0 and a for loop

I recently just converted my code to the Swift 3.0 syntax that came with the Xcode 8 beta. I ran into several lines of code that I needed to change in order for the code to work with the latest syntax. I was able to correct all lines of code except for an error that I get regarding a for loop that I use to allow my background image to loop continuously.
The exact error message that I get is: Ambiguous reference to member '..<'
for i:CGFloat in 0 ..< 3 {
let background = SKSpriteNode(texture: backgroundTexture)
background.position = CGPoint(x: backgroundTexture.size().width/2 + (backgroundTexture.size().width * i), y: self.frame.midY)
background.size.height = self.frame.height
background.run(movingAndReplacingBackground)
self.addChild(background)
}
Don't use a floating point type as loop index
for i in 0 ..< 3 {
let background = SKSpriteNode(texture: backgroundTexture)
background.position = CGPoint(x: backgroundTexture.size().width/2 + (backgroundTexture.size().width * CGFloat(i)), y: self.frame.midY)
background.size.height = self.frame.height
background.run(movingAndReplacingBackground)
self.addChild(background)
}
Try with this:
for i in 0..<3{
let index = CGFloat(i)
//Your Code
let background = SKSpriteNode(texture: backgroundTexture)
background.position = CGPoint(x: backgroundTexture.size().width/2 + (backgroundTexture.size().width * index), y: self.frame.midY)
background.size.height = self.frame.height
background.run(movingAndReplacingBackground)
self.addChild(background)
}
The problem is you are performing for-loop on Int and you are also specifying it as a CGFloat. So, there a confusing between both the types.

Improper width and height for second monitor from GetMonitorInfo and GetDeviceCaps

I am trying to get the top left x,y and bottom right x,y. And calculat the width and height of displays.
My secondary monitor is 1920x1080 as seen in my display settings screenshot:
I am getting the monitor dimensions in two ways. The code below is js-ctypes but I simplified out all the error checking and other ctypes stuff and tried to make it look like c. But this is a winapi issue not ctypes hence I didn't tag the topic with it.
First approach:
cPoint = POINT();
GetCursorPos(&cPoint);
cMon = MonitorFromPoint(cPoint, MONITOR_DEFAULTTONEAREST);
cMonInfo = MONITORINFOEX();
cMonInfo.cbSize = MONITORINFOEX.size;
GetMonitorInfo(cMon, &cMonInfo);
lpszDriver = null;
lpszDevice = cMonInfo.szDevice;
xTopLeft = cMonInfo.rcMonitor.left;
yTopLeft = cMonInfo.rcMonitor.top;
nWidth = cMonInfo.rcMonitor.right - xTopLeft;
nHeight = cMonInfo.rcMonitor.bottom - yTopLeft;
This is giving me a rect of the following:
_RECT(-1920, -1080, -640, -360)
Doing right - left gives 1280
Doing bottom - top gives 720
The dimensions are definitely wrong. It should have been width of 1920 and height of 1080.
I then try the second method:
hdcScreen = CreateDC(lpszDriver, lpszDevice, null, null);
nWidth = GetDeviceCaps(hdcScreen, HORZRES);
nHeight = GetDeviceCaps(hdcScreen, VERTRES);
This gives me the same thing, width of 1280 and height of 720. My mind is boggled! How can I get 1920x1080?
This same method gives me correct dimensions for my primary monitor, so I am very confused.
EDIT
I just now tried a third method, and still same issues:
var jsMonitorEnumProc = function(hMonitor, hdcMonitor, lprcMonitor, dwData) {
xTopLeft = lprcMonitor.contents.left;
yTopLeft = lprcMonitor.contents.top;
nWidth = lprcMonitor.contents.right - xTopLeft;
nHeight = lprcMonitor.contents.bottom - yTopLeft;
return true;
}
EnumDisplayMonitors(null, null, jsMonitorEnumProc, 0);
This gives me rects of the following:
_RECT(0, 0, 1280, 1024)
_RECT(-1920, -1080, -640, -360)
The first one is my primary monitor and we see doing bottom - top gives 1280 and right - left gives 1024 which is correct my primary monitor is 1280 x 1024.
But the second monitor again is -360 - -1080 for 720 height and -640 - -1920 for 1280 width. I am using this to take screenshots of all the monitors and second ones is coming out clipped.
In my non-dpi aware app 32bit Firefox on Win 8.1 64bit, I was able to get the proper dimensions by using EnumDisplaySettings using the DISPLAY_DEVICE struct of size 220.
js-ctypes:
// start - get all monitor resolutions
var iDevNum = -1;
while (true) {
iDevNum++;
var lpDisplayDevice = ostypes.TYPE.DISPLAY_DEVICE();
lpDisplayDevice.cb = ostypes.TYPE.DISPLAY_DEVICE.size;
var rez_EnumDisplayDevices = ostypes.API('EnumDisplayDevices')(null, iDevNum, lpDisplayDevice.address(), 0);
//console.info('rez_EnumDisplayDevices:', rez_EnumDisplayDevices.toString(), uneval(rez_EnumDisplayDevices), cutils.jscGetDeepest(rez_EnumDisplayDevices));
if (cutils.jscEqual(rez_EnumDisplayDevices, 0)) { // ctypes.winLastError != 0
// iDevNum is greater than the largest device index.
break;
}
console.info('lpDisplayDevice.DeviceName:', lpDisplayDevice.DeviceName.readString()); // "\\.\DISPLAY1" till "\\.\DISPLAY4"
if (lpDisplayDevice.StateFlags & ostypes.CONST.DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
console.log('is monitor');
var dm = ostypes.TYPE.DEVMODE(); // SIZEOF_DEVMODE = 148
console.info('dm.size:', ostypes.TYPE.DEVMODE.size);
//dm.dmFields = ostypes.CONST.DM_PELSWIDTH;
//dm.dmSize = ostypes.TYPE.DEVMODE.size;
console.log('iDevNum:', iDevNum, lpDisplayDevice.DeviceName.readString());
var rez_EnumDisplaySettings = ostypes.API('EnumDisplaySettings')(lpDisplayDevice.DeviceName, ostypes.CONST.ENUM_CURRENT_SETTINGS, dm.address());
//console.info('rez_EnumDisplaySettings:', rez_EnumDisplaySettings.toString(), uneval(rez_EnumDisplaySettings), cutils.jscGetDeepest(rez_EnumDisplaySettings));
//console.info('dm:', dm.toString());
collMonInfos.push({
x: parseInt(cutils.jscGetDeepest(dm.u.dmPosition.x)),
y: parseInt(cutils.jscGetDeepest(dm.u.dmPosition.y)),
w: parseInt(cutils.jscGetDeepest(dm.dmPelsWidth)),
h: parseInt(cutils.jscGetDeepest(dm.dmPelsHeight)),
screenshot: null, // for winnt, each collMonInfos entry has screenshot data
otherInfo: {
nBPP: parseInt(cutils.jscGetDeepest(dm.dmBitsPerPel)),
lpszDriver: null,
lpszDevice: lpDisplayDevice.DeviceName
}
});
}
}
// end - get all monitor resolutions

R: Change icon of Tcltk window in Mac and Linux

I have created a progress bar to keep tabs on the execution of some R scripts. And I want to insert a custom icon in the bar instead of the default 'Tk' one. I am able to do this on Windows using a .ico file and the following command
tcl('wm', 'iconbitmap', .win, 'Icon.ico')
But I am a loss about how to do the same in Mac OSX and Linux. Obviously, the .ico format doesn't work but neither does .png, .jpg, .bmp, .xbm or .xpm. Any suggestion on how I could proceed? Sample image and progress bar code attached below:-
Sample image http://tinypic.com/r/jt8efn/6 - http://tinypic.com/r/jt8efn/6
tkProgressBar2 <- function (title = 'Test progress bar', label = '', min = 0, max = 100, initial = 0, width = 300, userfn='helvetica', backg='white') {
useText <- FALSE
have_ttk <- as.character(tcl('info', 'tclversion')) >= '8.5'
if (!have_ttk && as.character(tclRequire('PBar')) == 'FALSE') useText <- TRUE
.win <<- tktoplevel(background=backg)
tkfocus()
tcl('wm', 'geometry', .win, '500x100+450+350')
tcl('wm', 'iconbitmap', .win, '#Icon.xbm')
.val <- initial
.killed <- FALSE
tkwm.geometry(.win, sprintf('%dx80', width + 40))
tkwm.title(.win, title)
fn <- tkfont.create(family = userfn, size = 12)
if (useText) {
.lab <- tklabel(.win, text = label, font = fn, padx = 0, background=backg)
tkpack(.lab, side = 'left')
fn2 <- tkfont.create(family = userfn, size = 16)
.vlab <- tklabel(.win, text = '0%', font = fn2, padx = 20, background=backg)
tkpack(.vlab, side = 'right')
up <- function(value) {
if (!is.finite(value) || value < min || value > max) return()
.val <<- value
tkconfigure(.vlab, text = sprintf('%d%%', round(100 * (value - min)/(max - min))))
}
} else {
.lab <- tklabel(.win, text = label, font = fn, pady = 0, background=backg)
.tkval <- tclVar(0)
tkpack(.lab, side = 'top')
tkpack(tklabel(.win, text = '', font = fn, background=backg), side = 'bottom')
pBar <- if (have_ttk)
ttkprogressbar(.win, length = width, variable = .tkval) else
tkwidget(.win, 'ProgressBar', width = width, variable = .tkval)
tkpack(pBar, side = 'bottom')
up <- function(value) {
if (!is.finite(value) || value < min || value > max) return()
.val <<- value
tclvalue(.tkval) <<- 100 * (value - min)/(max - min)
}
}
getVal <- function() .val
kill <- function() if (!.killed) {
tkdestroy(.win)
.killed <<- TRUE
}
title <- function(title) tkwm.title(.win, title)
lab <- function(label) tkconfigure(.lab, text = label)
tkbind(.win, '<Destroy>', function() stop())
up(initial)
structure(list(getVal = getVal, up = up, title = title, label = lab, kill = kill), class = 'tkProgressBar')
}
pb <- tkProgressBar2(title='Performing k-Means clustering', label='Some information in %', min=0, max=100, initial=0, width=400, userfn='verdana', backg='white')
On Linux you set the icon with wm iconphoto; wm iconbitmap does something else entirely. To do that, you'll need to create a photo image with the image data in it.
I'm guessing that you write this in R as:
tcl('wm', 'iconphoto', .win, tcl('image', 'create', 'photo', '-file', 'Icon.gif'))
I'm not quite sure which image formats are supported by the version of Tk you're using, including any image format support packages it has available. The minimal set is GIF and PPM unless you're (bravely) using 8.6, when PNG is also available by default.
(You can also create the content of a photo image programatically, but that's slow for various reasons.)
OSX doesn't have window icons in the same sense; it's normal for each minimized window to just show a snapshot of itself when it is minimized to the dock.

Resources