Получение значений выбранных элементов
Имеется функция написанная другим программистом (К сожалению другую написать не получится и использовать придется только ее. Имеем то что имеем) Функция вызывает чек бокс с мульти выбором элементов и принимает 3 элемента и возвращает Bool:
- Заголовок окна "String"
- Варианты выбора "String"
- Переменная типа Integer, куда и будет возращено номер выбранного элемента
function SelectMultiVariantDialog(aTitle: String; aVariant: String; var aTupel: Integer): Boolean;
И так чек бокс вызывается и в переменную Tupel возвращается число, но возвращается не индекс выбранного элемента, а суммы элементов, то есть
При выборе элемента 1 = 1, 2 = 2, 3 = 4, 4 = 8, 5 = 16, 6 = 32, 7 = 64, 8 = 128 в переменную заносится соответствующее значение
И вот вопрос, при выборе множества элементов выдает сумму соответствующих значений, то есть 6 и 7 элемент нам выдаст в переменной 96. Как мне на основании этого определить какие элементы были выбраны. Может кто ни будь подскажет.
P.S. через aVariant я передаю варианты выбора для пользователя. Например:
- 1 3001
- 2 3002
- 3 3003
- ....
И даю возможность выбрать несколько вариантов. После выбора в aTupel передаётся битовое значение выбранного элемента или сумма битовых элементов(если выбрано несколько)
Я пытаюсь понять после получение значение в переменную aTupel, как мне понять какие элементы были выбраны, Например выбрали 1 и 2 вариант и теперь хочу получить значения выбранных элементов чтоб в дальнейшем можно было передать значения 3001 и 3002 передать для обработки в sql запрос(это уже отдельная история. И там все готово)
var aTupel: integer;
begin
SelectMultiVariantDialog('Пожалуйста выберите событие',
'Событие генерации отчёта 3001|Событие генерации отчёта 3002|' +
'Событие генерации отчёта 3003|Событие генерации отчёта 3004|',
aTupel);
end;
В SQL хочу передать эти события
where code in ('3001,3003,3007')
P.S.S. Я попробовал слепить то что мне тут порекомендовали и вроде получилось то что я ожидал. Представляю мое решение, вдруг кто посоветует более изящное решение
const ET_ZERO = $00;
const ET_ONE = $01;
const ET_TWO = $02;
const ET_THREE = $04;
const ET_FOUR = $08;
const ET_FIVE = $10;
const ET_SIX = $20;
const ET_SEVEN = $40;
const ET_EIGHT = $80;
var iActionsMask: integer;
var sActions: String;
begin
if iActionsMask <= 0 then
begin
if not SelectMultiVariantDialog('Выбирите события для получение отчета!',
'3001- аааа|3002- бббб|' +
'3003- вввв|3004- гггг|' +
'3005- дддд', iActionsMask) then Exit;
//ShowMessage(IntToStr(iActionsMask));
if iActionsMask <= 0 then
begin
ShowMessage('Ничего не выбрано!');
Exit;
end
else
begin
sActions:='';
if (iActionsMask and ET_ZERO) > 0 then
if Length(sActions) > 0 then sActions := sActions + ', 3001' else sActions := '3001';
if (iActionsMask and ET_ONE) > 0 then
if Length(sActions) > 0 then sActions := sActions + ', 3002' else sActions := '3002';
if (iActionsMask and ET_TWO) > 0 then
if Length(sActions) > 0 then sActions := sActions + ', 3003' else sActions := '3003';
if (iActionsMask and ET_THREE) > 0 then
if Length(sActions) > 0 then sActions := sActions + ', 3004' else sActions := '3004';
if (iActionsMask and ET_FOUR) > 0 then
if Length(sActions) > 0 then sActions := sActions + ', 3005' else sActions := '3005';
end;
end;
//ShowMessage('Выбраны позиции ' + sActions);
end;
Правда я переименовал переменные и
Ответы (3 шт):
Это называется не сумма, а битовый набор, где каждому флагу/значению соответствует один бит.
Можно проверить выставлен ли каждый бит применив логическое И с соответствующей маской (в которой выставлен только этот бит) вот так, например:
isOne := ret and $01 <> 0; // Выбран первый элемент
isTwo := ret and $02 <> 0; // Выбран второй элемент
isThre := ret and $04 <> 0; // Выбран третий элемент
isFour := ret and $08 <> 0; // Выбран четвертый элемент
isFive := ret and $10 <> 0; // Выбран пятый элемент
isSix := ret and $20 <> 0; // Выбран шестой элемент
isSeve := ret and $40 <> 0; // Выбран седьмой элемент
isEigh := ret and $80 <> 0; // Выбран восьмой элемент
Как будут выглядеть несколько флагов? Например 42, в битовом представлении, это будет 00101010 (2 + 8 + 32 в десятичном виде. Или же $02 + $08 + $20 в шестнадцатеричном)
P.S. Лучше и правильнее было бы перейти на перечисления:
type
TSomeFlag = (sfOne, sfTwo, sfThree, sfFour ...)
TSomeFlagSet = set of TSomeFlag;
var
ret: TSomeFlagSet;
isOne := sfOne in ret;
isTwo := sfTwo in ret;
...
В дополнение к ответу Kromster:
for i := 0 to 31 do
if (aTupel and (1 shl i)) <> 0 then
вывести i
@AzatGafarov, слишком мало контекста, чтобы советовать более изящное рещение. Но как вариант...
...
var
iActionsMask : integer;
sActions : string;
list : TStringList;
i : integer;
begin
// your code here...
list := TStringList.Create();
try
for i := 0 to 31 do
if ( iActionsMask and (1 shl i) ) <> 0 then
list.Add( (i + 3001).ToString() );
sActions := list.CommaText;
finally
list.Free();
end;
// your code here...
end;
UPD. Можно чуть иначе, без сдвигов...
type
TElement = 0..7;
...
var
iActionsMask : integer;
elements : set of TElement absolute iActionsMask;
sActions : string;
list : TStringList;
e : TElement;
begin
// your code here...
list := TStringList.Create();
try
for e := Low(TElement) to High(TElement) do
if ( e in elements ) then
list.Add( IntToStr(e + 3001) );
sActions := list.CommaText;
finally
list.Free();
end;
// your code here...
end;