Disable/Enable button based on which control has focus - textbox

What I'm trying to do here is loop through the different controls and if any of the controls got focus to disable a button. This is a loop that I used for another task, so I'm kinda basing it off of this...
Dim cControl As Control
For Each cControl In Me.controls
If Not cControl.Container Is framClient Then
If Mid(cControl.Name, 1, 3) = "txt" Or Mid(cControl.Name, 1, 3) = "msk" Or Mid(cControl.Name, 1, 3) = "cbo" Then
'WHAT I'm trying to do here is
'if cControl.gotfocus then
'cmdExit.enabled=false
'end if ' but it barks at me
'cControl.Enabled = False
End If
End If
Next
I didn't make these text boxes in an array and I do not want to go through each text box to see if got focus and do whatever. Please take a look.

In vb6 only one control can have focus: the ActiveControl, so there's no point in looping and asking if the control has focus.
If you need to do something based on whether a certain control with a particular name has focus you could do this:
cmdExit.Enabled = (Me.ActiveControl.Name = "MyTextBox")
If you need to do it based on whether any TextBox has focus:
If TypeOf Me.ActiveControl Is TextBox Then
cmdExit.Enabled = false
Else
cmdExit.Enabled = true
End If

You can go ahead with Subclassing of text boxes as suggested in this SO Post.
As the post suggests, you have to do this exercise for every form where you have this requirement. I think, from your post that you have to do it only for one form.

Related

Call the name of a Texbox with number changing in Visual Basic 6

I'm use Visual Basic 6 to create a table with many Textbox which named txtNo1, txtNo2, txtNo3,...
I want to use the "For...Next..." loop to assign a content to these Textbox.
How can I call all these Textbox in the simplest way?
For i = 1 to 100
txtNo (......) .txt = "ABC"
Next i
Instead of using unique textboxes, each with a unique name, you should use a (textbox) control array:
Place the 1st textbox on the form, name it 'txtNo'
Copy it and paste it onto the form
VB will ask you "There's already a control named 'txtNo'. Would you like to create a control array?". Answer "Yes"
Paste as the textbox as many times as you need it
Then your code looks like
' Control arrays typically start at index 0
For i = 0 to 100
txtNo(i) .txt = "ABC"
Next i
Jim Mack's solution works as well, code for it:
' Assuming your form is named 'Form1'
For each ctrl in Form1.Controls
If TypeOf ctrl Is Textbox
For i = 1 To 100
If ctrl.Name = "txtNo" & CStr(i) Then
ctrl.Text = "ABC"
End If
End If
End If
It's a bit more complex, but therefore more flexible as works with multiple control types (in one loop).
If you need an easiest way to create your textboxes as a table, you can Load the controls at runtime. You have to add only the first TextBox control to your form, set the name to "txtNo", and Index to 0 in the Properties window.
In your code, call Load() to create additional controls, and you can set the Top/Left and other properties
For i = 1 To 100
Load txtNo(i)
txtNo(i).Top = txtNo(i - 1).Top + txtNo(i - 1).Height + 150
txtNo(i).Left = txtNo(i - 1).Left
txtNo(i).Text = "Textbox " & i
txtNo(i).Visible = True
Next i
If you need again to change any control property, from your list of controls, you can iterate only over your control list, instead of all controls of your Form
For i = txtNo.LBound() To txtNo.UBound()
Form1.Controls("txtNo")(i).Text = "New text " & i
Next i

Only show title bar on floating windows

In awesome 4.0, is there a way to only display the titlebar on floating windows?
Looking at the docs, there doesn't seem to be an option out of the box.
To specify; I'm looking for a solution that work when I dynamically switch windows between tiling and floating.
A bit late, but I wanted to do this too and I got it mostly working. It doesn't cover all the cases when you'd expect a client to show or hide its titlebar, but it's close enough for my use case.
It's rather simple, first you need to disable titlebars for every client, so add titlebars_enabled = false in the properties of the default rule matching all clients.
Then, when a client becomes floating you need to toggle on his titlebar, and toggle it off when it stops floating.
I wrote this little helper function to make the code clearer. It's rather simple, if s is true then show the bar, hide it otherwise. But there's a catch, in our case the windows never had a titlebar so it isn't created yet. We send the signal to have one built for us if the current one is empty.
-- Toggle titlebar on or off depending on s. Creates titlebar if it doesn't exist
local function setTitlebar(client, s)
if s then
if client.titlebar == nil then
client:emit_signal("request::titlebars", "rules", {})
end
awful.titlebar.show(client)
else
awful.titlebar.hide(client)
end
end
Now we can hook the property change:
--Toggle titlebar on floating status change
client.connect_signal("property::floating", function(c)
setTitlebar(c, c.floating)
end)
But that only applies to clients that changes states after being created. We need a hook for new clients that are born floating or in a floating tag:
-- Hook called when a client spawns
client.connect_signal("manage", function(c)
setTitlebar(c, c.floating or c.first_tag.layout == awful.layout.suit.floating)
end)
And finally, if the current layout is floating, clients don't have the floating property set, so we need to add a hook for layout changes to add the tittlebars on clients inside.
-- Show titlebars on tags with the floating layout
tag.connect_signal("property::layout", function(t)
-- New to Lua ?
-- pairs iterates on the table and return a key value pair
-- I don't need the key here, so I put _ to ignore it
for _, c in pairs(t:clients()) do
if t.layout == awful.layout.suit.floating then
setTitlebar(c, true)
else
setTitlebar(c, false)
end
end
end)
I didn't want to spend to much time on this so it doesn't cover cases where a client gets tagged in a floating layout, or when a client is tagged multiple times and one of those tag is floating.
Change
{ rule_any = {type = { "normal", "dialog" }
}, properties = { titlebars_enabled = true }
},
to
{ rule_any = {type = { "dialog" }
}, properties = { titlebars_enabled = true }
},
Niverton's solution works very well for simply switching from tiling to floating modes; however, floating windows will lose their titlebar when maximized and then unmaximized. To fix this, a better solution would be to replace
client.connect_signal("property::floating", function(c)
setTitlebar(c, c.floating)
end)
with
client.connect_signal("property::floating", function(c)
setTitlebar(c, c.floating or c.first_tag and c.first_tag.layout.name == "floating")
end)
This should fix the issue so that windows can be properly maximized without having to switch to tiling mode and back to get the titlebars again.
I found this general idea on a reddit post about the subject, provided by u/Ham5andw1ch. I have just simplified the code using Niverton's proposed function and some short-circuit logic.

WoW Addon - Dynamic tooltip while key is pressed

I've got a tooltip and I want it to show more detailed information if the SHIFT key is pressed/held. The following code works so far:
function myAddonFrame_OnEnter(self)
myAddon_GenerateTooltip(self)
end
function myAddonFrame_OnLeave(self)
GameTooltip:Hide()
end
function myAddon_GenerateTooltip(self)
GameTooltip:SetOwner(self or UIParent, "ANCHOR_LEFT")
GameTooltip:SetText(“myAddon”, 0.7, 0, 1)
GameTooltip:AddLine(" ", 1, 1, 1)
if IsShiftKeyDown() then
-- Show some more details, if the SHIFT key is pressed.
GameTooltip:AddLine(“Some detailed stuff about god and the world.”, 1, 1, 1)
GameTooltip:AddLine(“Even more great stuff to read.”, 0.9, 0.8, 0.1, 1)
else
-- Basic information to be displayed when no button is pressed.
GameTooltip:AddLine(“Some basic information. Yaaay!“, 1, 1, 1)
GameTooltip:AddLine(" ", 1, 1, 1)
GameTooltip:AddLine(“Hold SHIFT for more information…”, 0.5, 0.5, 0.5)
end
GameTooltip:Show()
end
But this only works if the SHIFT key is held before the mouse hovers the myAddonFrame. It also will display the detailed information even after releasing SHIFT as long as the mouse cursor remains on the myAddonFrame. But I want it dynamic!
My question here is:
How can I make the tooltip to refresh itself according to the SHIFT key when the mouse cursor stays on the frame?
I have in mind something like when I hover over an item in WoW and only as long as I hold the SHIFT key, that item will be compared with what I currently wear. I want exactly this effect, just within the same tooltip.
I hope somebody can push me in the right direction. I have tried using MODIFIER_STATE_CHANGED but I didn't get it working.
Oh, and while we are talking about toolips...here's a bonus question:
Is it possible to format them a bit? Bold, italics, fontsize, colorchanges for a single word in a line, etc. ? I didn't find anything particular here (wowprogramming.com), but maybe I overlooked it.
--- SOLVED ---
For the ones interested in the solution:
I used the code snippet of Nathanyel and adjusted it a bit. Because I use one XML file for all the frames and one corresponding LUA file for just the functions, I didn't wanted to create a new frame there. But I figgured out a way to use the existing myAddonFrame for the dynamic tooltip as well.
My code from above works perfectly and I just had to add the following:
-- [ALL THE CODE ABOVE!]
function myAddonFrame_OnLoad(frame)
frame:RegisterEvent("MODIFIER_STATE_CHANGED") -- Needed for the dynamic tool tip.
end
function myAddonFrame_OnEvent(frame, event, ...)
-- Fired, when any keyboard key is pressed.
local key, state = select(1, ...)
if (event == "MODIFIER_STATE_CHANGED") then
-- Switch the dynamic tooltip when the SHIFT key is held.
if myAddonFrame:IsMouseOver() and ((key == "LSHIFT") or (key == "RSHIFT")) then
myAddon_GenerateTooltip(frame)
end
end
end
That's it! Thanks to Nathanyel for the food for thought. :)
That event is indeed the key, but as you need to register it to a frame, preferably the one affected by the code, you should use a new frame for your tooltip:
local myFrame = CreateFrame("GameTooltip","myFrame",UIParent,"GameTooltipTemplate")
myFrame:SetScript("OnEvent",function(self, event, arg, ...)
if myFrame:IsShown()
and event == "MODIFIER_STATE_CHANGED"
and (arg = "LSHIFT" or arg = "RSHIFT") then
myAddon_GenerateTooltip() -- might need a parameter
end
end
myFrame:RegisterEvent("MODIFIER_STATE_CHANGED")
This simply re-populates the tooltip when either Shift key is pressed, and your function can react to the new state of the key.
Napkin code, slash some copy&paste from an addon where I used this method, so it might not be perfect, but enough to convey the concept.

World of Warcraft Lua - Changing frame:SetAttribute()

I'm working on an addon for World of Warcraft that completely overhauls the interface to adapt to my play style.
In this addon, I would like to have a large button that acts as a "main dps rotation" for my mage. I would like it to change what spell it casts based on what is optimal at any given time. It doesn't cast the spell automatically, it just presents the next best option for the user.
Here is my code so far:
print "Interface Overhaul : LOADED"
heatingUpIsActive = false
print(heatingUpIsActive)
local Button = CreateFrame("Button", "MyButton", UIParent,"SecureActionButtonTemplate")
Button:SetWidth(256)
Button:SetHeight(256)
Button:SetFrameStrata("HIGH")
Button:SetPoint("LEFT")
Button:SetText("Main Rotation")
Button:RegisterForClicks("AnyUp")
Button:SetAttribute("type", "spell")
Button:SetAttribute("spell", "Fireball")
Button:RegisterEvent("UNIT_AURA");
local function auraGained(self, event, ...)
if (UnitAura("player", "Heating Up")) then
if (heatingUpIsActive == false) then
heatingUpIsActive = true
print (heatingUpIsActive)
print ("Heating Up is active!")
Button:SetAttribute("spell", "Inferno Blast")
end
else
heatingUpIsActive = false
print("Heating Up is NOT active.")
print(heatingUpIsActive)
end
end
Button:SetScript("OnEvent", auraGained);
local tex = Button:CreateTexture("ARTWORK");
tex:SetPoint("LEFT")
tex:SetWidth(256)
tex:SetHeight(256)
tex:SetTexture("Interface\\AddOns\\InterfaceOverhaul\\Button2")
If heatingUpIsActive == true, I would like the button to cast ("spell", "Inferno Blast") instead of ("spell", "Fireball"), but it doesn't work if I place that into the correct part of the if statements.
Any thoughts?
As Mud said, you cannot rebind buttons in combat anymore. Blizzard made this change to prevent bots from being able to automate combat. Notably, in order to cast a spell you need to use one of the secure templates, and these secure templates only allow modification of the attributes that control what they do when you're not in combat. So you cannot have one button change spells mid-combat. Similarly, they also prevent you from modifying attributes like their position or visibility, so you cannot move buttons under the mouse either.
The best you can do is display a visual indicator of what spell should be cast, but rely on the user to actually press the correct button.

Triggering OK from the call back on GetParm

I am using the IUP.GetParm dialog to do a search and replace prompt.
The dialog supports 3 buttons, the first two OK and Cancel close the prompt and return to the main program flow.
The third button can be tracked in the parm_action function, what I want to do is use the third button to skip the item and close the dialog, but I can't work out if this is possible.
I have asked this on the IUP mailing list but have not yet had a response.
function param_action(dialog,index)
if index == -4 then
bSkip = true
return 1
end
end
bSkip = false
bConfirm,strFromString,strToString,bSkip =
iup.GetParam("Search and Replace",
param_action,
fhGetTag(ptrRecord)..'-'..fhGetTag(ptr)..
' '..fhGetDisplayText(ptrRecord).." %t\n"..
"Replace: "..strBoxType.."\n"..
"With: "..strBoxType.."\n"..
"btn: %u[Ok,Cancel,Skip] \n"
, strFromString,strToString)
if bConfirm and not(bSkip) then
-- replace string
end
To make this function currently you have to press the Skip button and then the Ok button.
Just re-posting the answer from the IUP mailing list here:
Inside the call-back, when the 3rd button is pressed, set the dialog
attribute "status" to "1" and call the function iup.ExitLoop().

Resources